MIRA
FactoryMacros.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_FACTORYMACROS_H_
48 #define _MIRA_FACTORYMACROS_H_
49 
50 #ifndef Q_MOC_RUN
51 #include <boost/mpl/assert.hpp>
52 #endif
53 
54 #include <platform/Typename.h>
55 
57 // class which will be abused as compile time error message
58 template< class T >
59 class ________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
60 {
61  virtual int FOR_CLASS();
62  virtual ~________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
63 };
64 
65 // class which will be abused as compile time error message
66 template< class T >
67 class ________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
68 {
69  virtual int FOR_CLASS();
70  virtual ~________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
71 };
72 
73 // class which will be abused as compile time error message
74 template< class T >
75 class ________________________________PLEASE_USE_THE__MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
76 {
77  virtual int FOR_CLASS();
78  virtual ~________________________________PLEASE_USE_THE__MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
79 };
80 
82 
83 namespace mira {
84 
86 
92 inline std::string mira_stripNameFromIdentifier( std::string const& identifier )
93 {
94  size_t pos = std::string::npos;
95  if ( identifier[identifier.length()-1] == '>' )
96  pos = identifier.rfind('<');
97  std::string tReturn = ( identifier.rfind("::",pos) != std::string::npos ) ?
98  identifier.substr( identifier.rfind("::",pos) + 2 )
99  : identifier;
100  return tReturn;
101 }
102 
104 
105 // *****************************************************************************
106 // *** ClassFactory MACROS (Protected)
107 // *****************************************************************************
108 
113 #define MIRA_OBJECT_BASE( classIdentifier ) \
114  friend class mira::ClassFactory; \
115  \
116  template<typename pCLASS, typename pBASECLASS> \
117  friend struct mira::FactoryRegisterClassHelper; \
118  \
119  template<typename pCLASS> \
120  friend class mira::TClass; \
121 \
122 public: \
123  \
124  mira::TClass<classIdentifier> const& getClass() const { \
125  /* This should do the trick, since all TClasses should be of the same*/\
126  /* structure and size. However, if you get a serious error here, keep*/\
127  /* it private because i will be really really disenchanted otherwise.*/\
128  return \
129  static_cast<mira::TClass<classIdentifier> const&>( internalGetClass() ); \
130  } \
131  \
132  \
133  static mira::TClass<classIdentifier> const& CLASS() { \
134  return _CLASS(); \
135  } \
136 \
137 protected: \
138  \
139  virtual mira::Class& internalGetClass() const { \
140  return _CLASS(); \
141  } \
142  static mira::TClass<classIdentifier>& _staticClassObject( \
143  std::string const& identifier, \
144  std::string const& name, \
145  bool libLoaded);
146 
148 
149 // *****************************************************************************
150 // *** ClassFactory MACROS (Public)
151 // *****************************************************************************
152 
159 #define MIRA_NAMEDOBJECT( classIdentifier, className ) \
160  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
161  \
162  \
163  static mira::TClass<classIdentifier>& _CLASS() { \
164  return _staticClassObject( mira::typeName<classIdentifier>(), \
165  #className, true ); \
166  } \
167 private: \
168  \
169  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
170  { \
171  /* No meta info given -> do nothing */ \
172  }
173 
175 
183 #define MIRA_OBJECT( classIdentifier ) \
184  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
185  \
186  \
187  static mira::TClass<classIdentifier>& _CLASS() { \
188  return _staticClassObject( mira::typeName<classIdentifier>(), \
189  mira::mira_stripNameFromIdentifier( \
190  mira::typeName<classIdentifier>() ), true ); \
191  } \
192 private: \
193  \
194  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
195  { \
196  /* No meta info given -> do nothing */ \
197  }
198 
200 
208 #define MIRA_META_OBJECT( classIdentifier, MetaInfo ) \
209  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
210  \
211  \
212  static mira::TClass<classIdentifier>& _CLASS() { \
213  return _staticClassObject( mira::typeName<classIdentifier>(), \
214  mira::mira_stripNameFromIdentifier( \
215  mira::typeName<classIdentifier>() ), true ); \
216  } \
217 private: \
218  \
219  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
220  { \
221  /* append given meta information to the map */ \
222  boost::assign::insert( metaMap ) MetaInfo; \
223  }
224 
226 
239 #define MIRA_ABSTRACT_OBJECT( classIdentifier ) \
240  MIRA_META_OBJECT( MIRA_PPARAM( classIdentifier ), ("AbstractClass", mira::typeName<classIdentifier>()) )
241 
246 #define MIRA_ABSTRACT_META_OBJECT( classIdentifier, MetaInfo ) \
247  MIRA_META_OBJECT( MIRA_PPARAM( classIdentifier ), ("AbstractClass", mira::typeName<classIdentifier>())MetaInfo )
248 
250 
257 #define MIRA_CLASS_REGISTER( Class, ... ) \
258  /* generate error message if macro is not used in global namespace */ \
259  template <> int \
260  ________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________ \
261  <Class>::FOR_CLASS() { return 0; } \
262  MIRA_REGISTRAR( MIRA_PPARAM( mira::FactoryRegisterClass<Class, __VA_ARGS__> ) ) \
263  mira::TClass<Class>& Class::_staticClassObject(std::string const& identifier, \
264  std::string const& name, \
265  bool libLoaded) { \
266  static mira::TClass<Class> sClass(identifier, name, libLoaded); \
267  return sClass; \
268  }
269 
274 #define MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR(CLASS) \
275  namespace mira { \
276  template<> \
277  class HasPublicDefaultConstructor<CLASS> : public std::false_type {}; \
278  }
279 
280 inline std::string replaceTemplateGeneric( std::string const& genericIdent,
281  std::string const& specialIdent )
282 {
283  size_t tFirstOccGeneric = genericIdent.find('<');
284  size_t tLastOccGeneric = genericIdent.rfind('>');
285  size_t tFirstOccSpecial = specialIdent.find('<');
286  size_t tLastOccSpecial = specialIdent.rfind('>');
287 
288  assert( tFirstOccGeneric != std::string::npos &&
289  tLastOccGeneric != std::string::npos );
290 
291  assert( tFirstOccSpecial != std::string::npos &&
292  tLastOccSpecial != std::string::npos );
293 
294  std::string tReturnValue = genericIdent;
295 
296  return tReturnValue.replace( tFirstOccGeneric, tLastOccGeneric-tFirstOccGeneric,
297  specialIdent.substr( tFirstOccSpecial,
298  tLastOccSpecial - tFirstOccSpecial ) );
299 }
300 
302 
303 #define MIRA_INTERNAL_OPEN_NAMESPACE(r,data,t) \
304  namespace t {
305 
306 #define MIRA_INTERNAL_CLOSE_NAMESPACE(r,data,t) }
307 
310 #define MIRA_VA_NUM_ARGS(...) MIRA_VA_NUM_ARGS_IMPL(__VA_ARGS__,5,4,3,2,1)
311 #define MIRA_VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N
312 
313 
314 // see: http://www.mail-archive.com/boost@lists.boost.org/msg03318.html
315 #define MIRA_MAKE_SEQ(size, rel) MIRA_MAKE_SEQ_D(size, rel)
316 #define MIRA_MAKE_SEQ_D(size, rel) \
317  BOOST_PP_CAT( \
318  MIRA_MAKE_SEQ_A_ ## size rel, \
319  0X0 \
320  )() \
321 
322 
323 // size 1
324 #define MIRA_MAKE_SEQ_A_1(a) ((a)) MIRA_MAKE_SEQ_B_1
325 #define MIRA_MAKE_SEQ_B_1(a) ((a)) MIRA_MAKE_SEQ_A_1
326 
327 #define MIRA_MAKE_SEQ_A_10X0()
328 #define MIRA_MAKE_SEQ_B_10X0()
329 
330 // size 2
331 #define MIRA_MAKE_SEQ_A_2(a, b) ((a, b)) MIRA_MAKE_SEQ_B_2
332 #define MIRA_MAKE_SEQ_B_2(a, b) ((a, b)) MIRA_MAKE_SEQ_A_2
333 
334 #define MIRA_MAKE_SEQ_A_20X0()
335 #define MIRA_MAKE_SEQ_B_20X0()
336 
337 // size 3
338 #define MIRA_MAKE_SEQ_A_3(a, b, c) ((a, b, c)) MIRA_MAKE_SEQ_B_3
339 #define MIRA_MAKE_SEQ_B_3(a, b, c) ((a, b, c)) MIRA_MAKE_SEQ_A_3
340 
341 #define MIRA_MAKE_SEQ_A_30X0()
342 #define MIRA_MAKE_SEQ_B_30X0()
343 
344 // size 4
345 #define MIRA_MAKE_SEQ_A_4(a, b, c, d) ((a, b, c, d)) MIRA_MAKE_SEQ_B_4
346 #define MIRA_MAKE_SEQ_B_4(a, b, c, d) ((a, b, c, d)) MIRA_MAKE_SEQ_A_4
347 
348 #define MIRA_MAKE_SEQ_A_40X0()
349 #define MIRA_MAKE_SEQ_B_40X0()
350 
351 // size 5
352 #define MIRA_MAKE_SEQ_A_5(a, b, c, d, e) ((a, b, c, d, e)) MIRA_MAKE_SEQ_B_5
353 #define MIRA_MAKE_SEQ_B_5(a, b, c, d, e) ((a, b, c, d, e)) MIRA_MAKE_SEQ_A_5
354 
355 #define MIRA_MAKE_SEQ_A_50X0()
356 #define MIRA_MAKE_SEQ_B_50X0()
357 
358 // size 6
359 #define MIRA_MAKE_SEQ_A_6(a, b, c, d, e, f) ((a, b, c, d, e, f)) MIRA_MAKE_SEQ_B_6
360 #define MIRA_MAKE_SEQ_B_6(a, b, c, d, e, f) ((a, b, c, d, e, f)) MIRA_MAKE_SEQ_A_6
361 
362 #define MIRA_INTERNAL_PRINT_TOKEN(TOKEN) #TOKEN
363 
364 #define MIRA_DO_NOTHING(Sequence,StartId)
365 
366 #define MIRA_INTERNAL_NAMESPACE_FOLD(r,data,t) \
367  t::data
368 
369 #define MIRA_INTERNAL_CONC_NAMESPACE_IMPL(Sequence, StartId) \
370  BOOST_PP_SEQ_FOLD_RIGHT(MIRA_INTERNAL_NAMESPACE_FOLD,,BOOST_PP_SEQ_REST_N(StartId,Sequence))
371 
372 #define MIRA_INTERNAL_CONC_NAMESPACE(Sequence,StartId) \
373  /* check if namespace size is greater zero and delay evaluation */ \
374  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( BOOST_PP_SEQ_REST_N( StartId, Sequence) ), \
375  /* length of namespace is greater zero */ \
376  MIRA_INTERNAL_CONC_NAMESPACE_IMPL \
377  /* we do not have a namespace -> do nothing */ \
378  , MIRA_DO_NOTHING )(Sequence, StartId)
379 
380 #define MIRA_INTERNAL_TEMPLATE_CLASS_REGISTER( r, Args, TmplSpec) \
381  /* Args(0) - contains the Class itself */ \
382  /* Args(1) - number of parents k */ \
383  /* Args(2) - number of template parameters */ \
384  /* Args(3) - address n of first namespace token in sequence Args */ \
385  /* Args(4 -- 4+k) - parents */ \
386  /* Args(n -- end) - namespace */ \
387  MIRA_REGISTRAR( MIRA_PPARAM( mira::FactoryRegisterClass< \
388  /* the folding process adds the namespace, if the namesapce sequence*/ \
389  /* length is greater than zero (with delayed evaluation) */ \
390  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( BOOST_PP_SEQ_REST_N( \
391  BOOST_PP_SEQ_ELEM(3,Args),Args) ), \
392  /* length of namespace is greater zero */ \
393  MIRA_INTERNAL_CONC_NAMESPACE_IMPL \
394  /* we do not have a namespace -> do nothing */ \
395  , MIRA_DO_NOTHING )( Args, BOOST_PP_SEQ_ELEM(3,Args) ) \
396  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR( BOOST_PP_SEQ_ELEM(2,Args), TmplSpec)>, \
397  BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_SUBSEQ(Args,4,BOOST_PP_SEQ_ELEM(1,Args)))> ) ) \
398 
399 
400 #define MIRA_INTERNAL_TEMPLATE_CLASS_STATIC( r, Args, TmplSpec) \
401  /* Args(0) contains the Class itself */ \
402  /* Args(1) contains the number of template parameters */ \
403  template<> mira::TClass<\
404  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >& \
405  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)>::_staticClassObject( \
406  std::string const& identifier, \
407  std::string const& name, \
408  bool libLoaded) { \
409  static mira::TemplateClass<BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> > \
410  sClass(identifier, name, libLoaded); \
411  return sClass; \
412  } \
413 
414 
415 #define MIRA_TMPL_SPEC_CONCAT(r, data, i, elem) "," BOOST_PP_STRINGIZE(elem)
416 
417 #define TAIL_NAME( Seq ) \
418  BOOST_PP_SEQ_FOR_EACH_I( MIRA_TMPL_SPEC_CONCAT, , Seq)
419 
420 #define MIRA_INTERNAL_TEMPLATE_IDENTIFIER( r, Args, TmplSpec) \
421  /* Args(0) contains the Class itself */ \
422  /* Args(1) contains the number of template parameters */ \
423  /* Args(2-n) contains the namespace */ \
424  template<> \
425  /* the folding process adds the namespace */ \
426  std::string const& TemplateClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
427  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getIdentifier() const { \
428  /* we should use a combination of the generic and the specialized */ \
429  /* here since the generic string should include the namespace.*/ \
430  static std::string tIdent = replaceTemplateGeneric( \
431  TClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
432  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getIdentifier(), \
433  "<" \
434  BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_SEQ_ELEM(1,Args),TmplSpec))) \
435  /* use for_each_i here since recursion of fore_each is not allowed */ \
436  BOOST_PP_SEQ_FOR_EACH_I( MIRA_TMPL_SPEC_CONCAT, , BOOST_PP_SEQ_TAIL(BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec))) \
437  ">" ); \
438  return tIdent; \
439  } \
440  \
441  template<> \
442  /* the folding process adds the namespace */ \
443  std::string const& TemplateClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
444  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getName() const { \
445  static std::string tName = mira_stripNameFromIdentifier( \
446  getIdentifier() ); \
447  return tName; \
448  } \
449 
450 
464 #define MIRA_TEMPLATE_CLASS_REGISTER( Namespace, Class, TmplSpec, ... ) \
465  MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, 1, MIRA_MAKE_SEQ(1,TmplSpec), __VA_ARGS__ )
466 
479 #define MIRA_VARTEMPLATE_CLASS_REGISTER( Namespace, Class, NumTmplPrm, TmplSpec, ... ) \
480  MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, NumTmplPrm, MIRA_MAKE_SEQ(NumTmplPrm,TmplSpec), __VA_ARGS__ )
481 
483 
484 #define MIRA_TMPL_SIG_FROM_SEQ( NumTmplPrm, SeqId, Sequence )\
485  BOOST_PP_TUPLE_REM_CTOR( NumTmplPrm, BOOST_PP_SEQ_ELEM(SeqId,Sequence) )
486 
487 #define MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, NumTmplPrm, TmplSpec, ... ) \
488  /* generate error message if macro is not used in global namespace */ \
489  template <> int \
490  ________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________\
491  <MIRA_INTERNAL_CONC_NAMESPACE(Namespace,0)Class \
492  <MIRA_TMPL_SIG_FROM_SEQ(NumTmplPrm,0,TmplSpec)> >::FOR_CLASS() { return 0; } \
493  /* the following lines build up a sequence for the internal register macro*/\
494  /* structure: (Class)(Number of Parents)(Address of first namespace token */\
495  /* in the sequence)(Parents as sequence)(Namespace as sequence) */ \
496  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_CLASS_REGISTER, \
497  (Class) \
498  (MIRA_VA_NUM_ARGS(__VA_ARGS__))(NumTmplPrm)(BOOST_PP_ADD(MIRA_VA_NUM_ARGS(__VA_ARGS__),4))\
499  BOOST_PP_TUPLE_TO_SEQ(MIRA_VA_NUM_ARGS(__VA_ARGS__),(__VA_ARGS__)) \
500  Namespace,TmplSpec) \
501  \
502  /* we can only specialize the the template in the corresponding namespace */\
503  /* check if length of namespace is greater than zero */ \
504  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( Namespace ), \
505  /* length of namespace is greater zero */ \
506  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_OPEN_NAMESPACE,~,Namespace) \
507  /* length of namespace is zero -> do nothing */ \
508  , ) \
509  /* we have to combine all parameters in a boost pp sequence in order */ \
510  /* to pass them to the internal macro */ \
511  /* Register the class at the factory */ \
512  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_CLASS_STATIC, \
513  (Class)(NumTmplPrm), TmplSpec) \
514  /* check if length of namespace is greater than zero */ \
515  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( Namespace ), \
516  /* length of namespace is greater zero */ \
517  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_CLOSE_NAMESPACE,~,Namespace) \
518  /* length of namespace is zero -> do nothing */ \
519  , ) \
520  \
521  namespace mira { \
522  /* Specialize the functions to obtain the template identifiers */ \
523  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_IDENTIFIER, \
524  (Class)(NumTmplPrm)Namespace,TmplSpec) \
525  }
526 
528 
530 
531 } // namespace
532 
533 #endif /* _MIRA_FACTORYMACROS_H_ */
534 
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Get compiler and platform independent typenames.
std::string mira_stripNameFromIdentifier(std::string const &identifier)
Auxiliary function to extract the class name from the given identifier.
Definition: FactoryMacros.h:92
std::string replaceTemplateGeneric(std::string const &genericIdent, std::string const &specialIdent)
Definition: FactoryMacros.h:280