libqi-api  2.8.7.4
 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_DETAIL_TYPEIMPL_HXX_
8 #define _QITYPE_DETAIL_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(qi::typeId<T>().name(), "default constructor"); return 0;}
41  static void createInPlace(void* ptr) {typeFail(qi::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(qi::typeId<T>().name(), "copy operator");}
57  static void* clone(void* src) { typeFail(qi::typeId<T>().name(), "clone"); return 0;}
58  static void cloneInPlace(void* ptr, void* src) { typeFail(qi::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(qi::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  using type = T;
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 " << qi::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  using type = T;
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  using 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 const TypeInfo result(qi::typeId<T>());
246  return result;
247  }
248 
249  static void* clone(void* src)
250  {
251  return Access::clone(src);
252  }
253 
254  static void destroy(void* ptr)
255  {
256  Access::destroy(ptr);
257  }
258 
259  static bool less(void* a, void* b)
260  {
261  return ::qi::detail::Less<T>()((T*)ptrFromStorage(&a), (T*)ptrFromStorage(&b));
262  }
263  };
264 
266 #define _QI_BOUNCE_TYPE_METHODS_NOCLONE(Bounce) \
267  const ::qi::TypeInfo& info() override { return Bounce::info();} \
268  void* initializeStorage(void* ptr=0) override { return Bounce::initializeStorage(ptr);} \
269  void* ptrFromStorage(void**s) override { return Bounce::ptrFromStorage(s);} \
270  bool less(void* a, void* b) override { return Bounce::less(a, b);}
271 
273 #define _QI_BOUNCE_TYPE_METHODS(Bounce) \
274  _QI_BOUNCE_TYPE_METHODS_NOCLONE(Bounce) \
275  void* clone(void* ptr) override { return Bounce::clone(ptr);} \
276  void destroy(void* ptr) override { Bounce::destroy(ptr);}
277 
279 #define _QI_BOUNCE_TYPE_METHODS_NOINFO(Bounce) \
280  void* initializeStorage(void* ptr=0) override { return Bounce::initializeStorage(ptr);} \
281  void* ptrFromStorage(void**s) override { return Bounce::ptrFromStorage(s);} \
282  void* clone(void* ptr) override { return Bounce::clone(ptr);} \
283  void destroy(void* ptr) override { Bounce::destroy(ptr);} \
284  bool less(void* a, void* b) override { return Bounce::less(a, b);}
285 
286  template < typename T, typename _Access = TypeByPointer<T> >
288  : public TypeInterface
289  {
290  public:
293  };
294 
299  template<typename T>
300  class TypeImpl: public DefaultTypeImpl<T>
301  {};
302 
303  // void
304  template<>
305  class TypeImpl<void>: public TypeInterface
306  {
307  public:
308  const TypeInfo& info() override
309  {
310  static TypeInfo result = TypeInfo(qi::typeId<void>());
311  return result;
312  }
313  // do not return 0 everywhere and provide a correct impl
314  // this may be used as void*, that's why we need to keep storage
315  void* initializeStorage(void* ptr) override { return ptr; }
316  void* ptrFromStorage(void** storage) override { return (void*)storage; }
317  void* clone(void* storage) override { return storage; }
318  void destroy(void* ptr) override {}
319  TypeKind kind() override { return TypeKind_Void; }
320  bool less(void* a, void* b) override { 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_DETAIL_TYPEIMPL_HXX_
static void destroy(void *storage)
Definition: typeimpl.hxx:210
const TypeInfo & info() override
Get the TypeInfo corresponding to this type.
Definition: typeimpl.hxx:308
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:33
static void * create()
Definition: typeimpl.hxx:33
static const TypeInfo & info()
Definition: typeimpl.hxx:243
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:233
static void destroy(void *src)
Definition: typeimpl.hxx:165
bool less(void *a, void *b) override
Definition: typeimpl.hxx:320
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
static void createInPlace(void *ptr)
Definition: typeimpl.hxx:34
static void createInPlace(void *ptr)
Definition: typeimpl.hxx:41
static bool less(void *a, void *b)
Definition: typeimpl.hxx:259
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:146
void destroy(void *ptr) override
Free all resources of a storage.
Definition: typeimpl.hxx:318
#define qiLogError(...)
Log in error mode.
Definition: log.hpp:120
static void * clone(void *src)
Definition: typeimpl.hxx:203
void * ptrFromStorage(void **storage) override
Definition: typeimpl.hxx:316
#define _QI_BOUNCE_TYPE_METHODS(Bounce)
Implement all methods of Type as bouncers to Bouncer.
Definition: typeimpl.hxx:273
Access API that stores a T* in storage.
Definition: typeimpl.hxx:136
static void destroy(void *ptr)
Definition: typeimpl.hxx:64
static void destroy(const U &ptr)
Definition: typeimpl.hxx:71
static void destroy(void *ptr)
Definition: typeimpl.hxx:254
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:249
static void copy(const T1 &d, const T2 &s)
Definition: typeimpl.hxx:56
static void * clone(void *src)
Definition: typeimpl.hxx:57
T src(const std::atomic< T > &x)
Definition: atomic.hpp:318
static void * initializeStorage(void *ptr=0)
Definition: typeimpl.hxx:192
TypeKind
Definition: fwd.hpp:54
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
void * initializeStorage(void *ptr) override
Definition: typeimpl.hxx:315
TypeKind kind() override
Definition: typeimpl.hxx:319
void * clone(void *storage) override
Allocate a storage and copy the value given as an argument.
Definition: typeimpl.hxx:317