libqi-api  2.4.3.28
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
typeimpl.hxx
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QITYPE_DETAILS_TYPEIMPL_HXX_
8 #define _QITYPE_DETAILS_TYPEIMPL_HXX_
9 
10 #include <set>
12 
13 
14 /* This file contains class to help implementing the Type interface.
15 */
16 namespace qi
17 {
18  namespace detail {
20  void QI_API typeFail(const char* typeName, const char* operation);
21 
22  /* Handle creation (create, createInPlace), copy (copy, clone, cloneInPlace), and
23  * destruction(destroy) of a given type.
24  * There is currently no portable way to detect if a given class has
25  * accesible constructor, destructor and/or copy operators.
26  * So we provide a reasonable default behavior (through our class/struct
27  * registration macros) and rely on the user to call the appropriate
28  * QI_TYPE_NOT_* macro to override.
29  */
30  template<typename T, bool b>
32  {
33  static void* create() { return new T();}
34  static void createInPlace(void* ptr) { new(ptr)T();}
35  };
36 
37  template<typename T>
38  struct TypeTraitCreate<T, false>
39  {
40  static void* create() { typeFail(typeid(T).name(), "default constructor"); return 0;}
41  static void createInPlace(void* ptr) {typeFail(typeid( T).name(), "default constructor");}
42  };
43 
44  template<typename T, bool b>
46  {
47  static void copy(void* dst, const void* src) { *(T*)dst = *(const T*)src;}
48  static void* clone(void* src) { return new T(*(T*)src);}
49  static void cloneInPlace(void* ptr, void* src) { new (ptr)T(*(T*)src);}
50  };
51 
52  template<typename T>
53  struct TypeTraitCopy<T, false>
54  {
55  template<typename T1, typename T2>
56  static void copy(const T1& d, const T2&s) {typeFail(typeid(T).name(), "copy operator");}
57  static void* clone(void* src) { typeFail(typeid(T).name(), "clone"); return 0;}
58  static void cloneInPlace(void* ptr, void* src) { typeFail(typeid(T).name(), "clone");}
59  };
60 
61  template<typename T, bool b>
63  {
64  static void destroy(void* ptr) { delete (T*)ptr;}
65  };
66 
67  template<typename T>
68  struct TypeTraitDestroy<T, false>
69  {
70  template<typename U>
71  static void destroy(const U& ptr) {typeFail(typeid(T).name(), "destructor");}
72  };
73 
74  /* Use a two-stage override mechanism.
75  * That way if a user uses our macro that specializes
76  * TypeManager on one of the versions below, she can still
77  * specializes the appropriate TypeManagerDefault{Struct,Class}.
78  */
79  template<typename T>
81  : public TypeTraitCreate<T, true>
82  , public TypeTraitCopy<T, true>
83  , public TypeTraitDestroy<T, true>
84  {};
85 
86  template<typename T>
88  : public TypeTraitCreate<T, false>
89  , public TypeTraitCopy<T, false>
90  , public TypeTraitDestroy<T, true>
91  {};
92 
93  template<typename T>
95  : public TypeTraitCreate<T, false>
96  , public TypeTraitCopy<T, false>
97  , public TypeTraitDestroy<T, false>
98  {};
99 
100  template<typename T>
101  struct TypeManagerNotConstructible // not constructible but copyable
102  : public TypeTraitCreate<T, false>
103  , public TypeTraitCopy<T, true>
104  , public TypeTraitDestroy<T, true>
105  {};
106 
107 
108  // TypeManager is accessed by this interface.
109  // Only things for which we are sure are marked constructible and clonable
110  template<typename T>
111  struct TypeManager
112  : public boost::mpl::if_c<
113  boost::is_function<T>::value,
114  TypeManagerNull<T>,
115  typename boost::mpl::if_c< boost::is_pod<T>::value,
116  TypeManagerDefaultStruct<T>,
117  TypeManagerDefaultInterface<T> >
118  ::type>::type {};
119 
120  // Except for boost::function which matches is_function and is copyable
121  template<typename T>
122  struct TypeManager<boost::function<T> >: public TypeManagerDefaultStruct<boost::function<T> >
123  {};
124  template<typename T>
125  struct TypeManager<const T>: public TypeManager<T>{};
126 
127  }
128 
129  /* To avoid the diamond inheritance problem (interface inheritance between
130  * for instance Type and IntTypeInterface, and we want to reuse implementations),
131  * Provide methods in a class that does not inherit from Type, and a macro
132  * to generate the virtual bouncers.
133  */
135  template <typename T, typename Manager=detail::TypeManager<T> >
137  {
138  public:
139  typedef T type;
140 
141  static void* ptrFromStorage(void** storage)
142  {
143  return *storage;
144  }
145 
146  static void* initializeStorage(void* ptr=0)
147  {
148  if (ptr)
149  return ptr;
150  //Warning:
151  // If T is not clonable (no copy constructor or operator=)
152  // add QI_TYPE_NOT_CLONABLE(T) next to the declaration of T
153  // in your code.
154  void* res = Manager::create();
155  if (!res)
156  qiLogError("qitype.bypointer") << "initializeStorage error on " << typeid(T).name();
157  return res;
158  }
159 
160  static void* clone(void* src)
161  {
162  return Manager::clone(src);
163  }
164 
165  static void destroy(void* src)
166  {
167  T* ptr = (T*)ptrFromStorage(&src);
168  Manager::destroy(ptr);
169  }
170  };
171 
172  // const ward
173  template <typename T>
174  class TypeByPointer<const T>: public TypeByPointer<T>
175  {};
176  // Helper to mark POD-like
177  template <typename T>
178  class TypeByPointerPOD: public TypeByPointer<T, detail::TypeManagerDefaultStruct<T> >{};
180  /* No longuer used since we have an in-place modification
181  * of AnyReference, as by-value storage would break reference semantic
182  */
183  template <typename T>
185  {
186  public:
187  typedef T type;
188  static void* ptrFromStorage(void** storage)
189  {
190  return storage;
191  }
192  static void* initializeStorage(void* ptr=0)
193  {
194  void* result = 0;
195  T* tresult=(T*)(void*)&result;
197 
198  if (ptr)
199  detail::TypeManager<T>::copy(tresult, (T*)ptr);
200 
201  return result;
202  }
203  static void* clone(void* src)
204  {
205  void* res;
206  detail::TypeManager<T>::cloneInPlace(&res, (T*)&src);
207  return res;
208  }
209 
210  static void destroy(void* storage)
211  {
212  T* ptr = (T*)ptrFromStorage(&storage);
213  ptr->~T();
214  }
215  };
216 
217  // const ward
218  template <typename T>
219  class TypeByValue<const T>: public TypeByValue<T>
220  {};
221 
222 
223  /* implementation of Type methods that bounces to the various aspect
224  * subclasses.
225  *
226  */
227  template < typename T, typename _Access = TypeByPointer<T> >
229  {
230  public:
231  typedef _Access Access;
232 
233  static void* initializeStorage(void* ptr=0)
234  {
235  return Access::initializeStorage(ptr);
236  }
237 
238  static void* ptrFromStorage(void** storage)
239  {
240  return Access::ptrFromStorage(storage);
241  }
242 
243  static const TypeInfo& info()
244  {
245  static TypeInfo* result = 0;
246  if (!result)
247  result = new TypeInfo(typeid(T));
248  return *result;
249  }
250 
251  static void* clone(void* src)
252  {
253  return Access::clone(src);
254  }
255 
256  static void destroy(void* ptr)
257  {
258  Access::destroy(ptr);
259  }
260 
261  static bool less(void* a, void* b)
262  {
263  return ::qi::detail::Less<T>()((T*)ptrFromStorage(&a), (T*)ptrFromStorage(&b));
264  }
265  };
266 
268 #define _QI_BOUNCE_TYPE_METHODS_NOCLONE(Bounce) \
269  virtual const ::qi::TypeInfo& info() { return Bounce::info();} \
270  virtual void* initializeStorage(void* ptr=0) { return Bounce::initializeStorage(ptr);} \
271  virtual void* ptrFromStorage(void**s) { return Bounce::ptrFromStorage(s);} \
272  virtual bool less(void* a, void* b) { return Bounce::less(a, b);}
273 
275 #define _QI_BOUNCE_TYPE_METHODS(Bounce) \
276  _QI_BOUNCE_TYPE_METHODS_NOCLONE(Bounce) \
277  virtual void* clone(void* ptr) { return Bounce::clone(ptr);} \
278  virtual void destroy(void* ptr) { Bounce::destroy(ptr);}
279 
281 #define _QI_BOUNCE_TYPE_METHODS_NOINFO(Bounce) \
282  virtual void* initializeStorage(void* ptr=0) { return Bounce::initializeStorage(ptr);} \
283  virtual void* ptrFromStorage(void**s) { return Bounce::ptrFromStorage(s);} \
284  virtual void* clone(void* ptr) { return Bounce::clone(ptr);} \
285  virtual void destroy(void* ptr) { Bounce::destroy(ptr);} \
286  virtual bool less(void* a, void* b) { return Bounce::less(a, b);}
287 
288  template < typename T, typename _Access = TypeByPointer<T> >
290  : public TypeInterface
291  {
292  public:
295  };
296 
301  template<typename T>
302  class TypeImpl: public DefaultTypeImpl<T>
303  {};
304 
305  // void
306  template<>
307  class TypeImpl<void>: public TypeInterface
308  {
309  public:
310  const TypeInfo& info()
311  {
312  static TypeInfo result = TypeInfo(typeid(void));
313  return result;
314  }
315  void* initializeStorage(void*) { return 0;}
316  void* ptrFromStorage(void** ) { return 0;}
317  void* clone(void*) { return 0;}
318  void destroy(void* ptr) {}
320  bool less(void* a, void* b) { return false;}
321  };
322 
323  //reference
324  template<typename T>
325  class TypeImpl<T&>: public TypeImpl<T>
326  {};
327 
328 
329 
330 }
331 
332 namespace _qi_
333 {
334  namespace qi
335  {
336  // Support for QI_TYPE_STRUCT_REGISTER and QI_TYPE_STRUCT_BOUNCE_REGISTER
337  template<typename T>
338  class TypeImpl
339  {};
340  }
341 }
342 
343 #endif // _QITYPE_DETAILS_TYPEIMPL_HXX_
static void destroy(void *storage)
Definition: typeimpl.hxx:210
static void * clone(void *src)
Definition: typeimpl.hxx:160
void destroy()
Stop and flush the logging system.
static void cloneInPlace(void *ptr, void *src)
Definition: typeimpl.hxx:49
#define QI_API
Definition: api.hpp:34
static void * create()
Definition: typeimpl.hxx:33
static const TypeInfo & info()
Definition: typeimpl.hxx:243
bool less(void *a, void *b)
Definition: typeimpl.hxx:320
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:233
static void destroy(void *src)
Definition: typeimpl.hxx:165
static void copy(void *dst, const void *src)
Definition: typeimpl.hxx:47
static void * ptrFromStorage(void **storage)
Definition: typeimpl.hxx:141
static void cloneInPlace(void *ptr, void *src)
Definition: typeimpl.hxx:58
DefaultTypeImplMethods< T, _Access > MethodsImpl
Definition: typeimpl.hxx:293
static void createInPlace(void *ptr)
Definition: typeimpl.hxx:34
static void createInPlace(void *ptr)
Definition: typeimpl.hxx:41
void * clone(void *)
Allocate a storage and copy the value given as an argument.
Definition: typeimpl.hxx:317
static bool less(void *a, void *b)
Definition: typeimpl.hxx:261
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:146
#define qiLogError(...)
Log in error mode.
Definition: log.hpp:113
static void * clone(void *src)
Definition: typeimpl.hxx:203
#define _QI_BOUNCE_TYPE_METHODS(Bounce)
Implement all methods of Type as bouncers to Bouncer.
Definition: typeimpl.hxx:275
Access API that stores a T* in storage.
Definition: typeimpl.hxx:136
static void destroy(void *ptr)
Definition: typeimpl.hxx:64
const TypeInfo & info()
Get the TypeInfo corresponding to this type.
Definition: typeimpl.hxx:310
static void destroy(const U &ptr)
Definition: typeimpl.hxx:71
void destroy(void *ptr)
Free all resources of a storage.
Definition: typeimpl.hxx:318
static void destroy(void *ptr)
Definition: typeimpl.hxx:256
void typeFail(const char *typeName, const char *operation)
Report a type operation failure.
static void * clone(void *src)
Definition: typeimpl.hxx:48
static void * clone(void *src)
Definition: typeimpl.hxx:251
static void copy(const T1 &d, const T2 &s)
Definition: typeimpl.hxx:56
static void * clone(void *src)
Definition: typeimpl.hxx:57
void * initializeStorage(void *)
Definition: typeimpl.hxx:315
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:192
TypeKind
Definition: fwd.hpp:53
void * ptrFromStorage(void **)
Definition: typeimpl.hxx:316
static void * ptrFromStorage(void **storage)
Definition: typeimpl.hxx:238
static void * ptrFromStorage(void **storage)
Definition: typeimpl.hxx:188
Access api that stores a T in storage.
Definition: typeimpl.hxx:184