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 #include <platform/Typename.h>
51 
53 // class which will be abused as compile time error message
54 template< class T >
55 class ________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
56 {
57  virtual int FOR_CLASS();
58  virtual ~________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
59 };
60 
61 // class which will be abused as compile time error message
62 template< class T >
63 class ________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
64 {
65  virtual int FOR_CLASS();
66  virtual ~________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
67 };
68 
69 // class which will be abused as compile time error message
70 template< class T >
71 class ________________________________PLEASE_USE_THE__MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________
72 {
73  virtual int FOR_CLASS();
74  virtual ~________________________________PLEASE_USE_THE__MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________() {}
75 };
76 
78 
79 namespace mira {
80 
82 
88 inline std::string mira_stripNameFromIdentifier( std::string const& identifier )
89 {
90  size_t pos = std::string::npos;
91  if ( identifier[identifier.length()-1] == '>' )
92  pos = identifier.rfind('<');
93  std::string tReturn = ( identifier.rfind("::",pos) != std::string::npos ) ?
94  identifier.substr( identifier.rfind("::",pos) + 2 )
95  : identifier;
96  return tReturn;
97 }
98 
100 
101 // *****************************************************************************
102 // *** ClassFactory MACROS (Protected)
103 // *****************************************************************************
104 
109 #define MIRA_OBJECT_BASE( classIdentifier ) \
110  friend class mira::ClassFactory; \
111  \
112  template<typename pCLASS, typename pBASECLASS> \
113  friend struct mira::FactoryRegisterClassHelper; \
114  \
115  template<typename pCLASS> \
116  friend class mira::TClass; \
117 \
118 public: \
119  \
120  mira::TClass<classIdentifier> const& getClass() const { \
121  /* This should do the trick, since all TClasses should be of the same*/\
122  /* structure and size. However, if you get a serious error here, keep*/\
123  /* it private because i will be really really disenchanted otherwise.*/\
124  return \
125  static_cast<mira::TClass<classIdentifier> const&>( internalGetClass() ); \
126  } \
127  \
128  \
129  static mira::TClass<classIdentifier> const& CLASS() { \
130  return _CLASS(); \
131  } \
132 \
133 protected: \
134  \
135  virtual mira::Class& internalGetClass() const { \
136  return _CLASS(); \
137  } \
138  static mira::TClass<classIdentifier>& _staticClassObject( \
139  std::string const& identifier, \
140  std::string const& name, \
141  bool libLoaded);
142 
144 
145 // *****************************************************************************
146 // *** ClassFactory MACROS (Public)
147 // *****************************************************************************
148 
155 #define MIRA_NAMEDOBJECT( classIdentifier, className ) \
156  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
157  \
158  \
159  static mira::TClass<classIdentifier>& _CLASS() { \
160  return _staticClassObject( mira::typeName<classIdentifier>(), \
161  #className, true ); \
162  } \
163 private: \
164  \
165  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
166  { \
167  /* No meta info given -> do nothing */ \
168  }
169 
171 
179 #define MIRA_OBJECT( classIdentifier ) \
180  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
181  \
182  \
183  static mira::TClass<classIdentifier>& _CLASS() { \
184  return _staticClassObject( mira::typeName<classIdentifier>(), \
185  mira::mira_stripNameFromIdentifier( \
186  mira::typeName<classIdentifier>() ), true ); \
187  } \
188 private: \
189  \
190  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
191  { \
192  /* No meta info given -> do nothing */ \
193  }
194 
196 
204 #define MIRA_META_OBJECT( classIdentifier, MetaInfo ) \
205  MIRA_OBJECT_BASE( MIRA_PPARAM( classIdentifier ) ) \
206  \
207  \
208  static mira::TClass<classIdentifier>& _CLASS() { \
209  return _staticClassObject( mira::typeName<classIdentifier>(), \
210  mira::mira_stripNameFromIdentifier( \
211  mira::typeName<classIdentifier>() ), true ); \
212  } \
213 private: \
214  \
215  static void addMetaInfo( std::map<std::string, std::string>& metaMap ) \
216  { \
217  /* append given meta information to the map */ \
218  boost::assign::insert( metaMap ) MetaInfo; \
219  }
220 
222 
235 #define MIRA_ABSTRACT_OBJECT( classIdentifier ) \
236  MIRA_META_OBJECT( MIRA_PPARAM( classIdentifier ), ("AbstractClass", mira::typeName<classIdentifier>()) )
237 
242 #define MIRA_ABSTRACT_META_OBJECT( classIdentifier, MetaInfo ) \
243  MIRA_META_OBJECT( MIRA_PPARAM( classIdentifier ), ("AbstractClass", mira::typeName<classIdentifier>())MetaInfo )
244 
246 
253 #define MIRA_CLASS_REGISTER( Class, ... ) \
254  /* generate error message if macro is not used in global namespace */ \
255  template <> int \
256  ________________________________PLEASE_USE_THE__MIRA_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________ \
257  <Class>::FOR_CLASS() { return 0; } \
258  MIRA_REGISTRAR( MIRA_PPARAM( mira::FactoryRegisterClass<Class, __VA_ARGS__> ) ) \
259  mira::TClass<Class>& Class::_staticClassObject(std::string const& identifier, \
260  std::string const& name, \
261  bool libLoaded) { \
262  static mira::TClass<Class> sClass(identifier, name, libLoaded); \
263  return sClass; \
264  }
265 
270 #define MIRA_NO_PUBLIC_DEFAULT_CONSTRUCTOR(CLASS) \
271  namespace mira { \
272  template<> \
273  class HasPublicDefaultConstructor<CLASS> : public std::false_type {}; \
274  }
275 
276 inline std::string replaceTemplateGeneric( std::string const& genericIdent,
277  std::string const& specialIdent )
278 {
279  size_t tFirstOccGeneric = genericIdent.find('<');
280  size_t tLastOccGeneric = genericIdent.rfind('>');
281  size_t tFirstOccSpecial = specialIdent.find('<');
282  size_t tLastOccSpecial = specialIdent.rfind('>');
283 
284  assert( tFirstOccGeneric != std::string::npos &&
285  tLastOccGeneric != std::string::npos );
286 
287  assert( tFirstOccSpecial != std::string::npos &&
288  tLastOccSpecial != std::string::npos );
289 
290  std::string tReturnValue = genericIdent;
291 
292  return tReturnValue.replace( tFirstOccGeneric, tLastOccGeneric-tFirstOccGeneric,
293  specialIdent.substr( tFirstOccSpecial,
294  tLastOccSpecial - tFirstOccSpecial ) );
295 }
296 
298 
299 #define MIRA_INTERNAL_OPEN_NAMESPACE(r,data,t) \
300  namespace t {
301 
302 #define MIRA_INTERNAL_CLOSE_NAMESPACE(r,data,t) }
303 
306 #define MIRA_VA_NUM_ARGS(...) MIRA_VA_NUM_ARGS_IMPL(__VA_ARGS__,5,4,3,2,1)
307 #define MIRA_VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N
308 
309 
310 // see: http://www.mail-archive.com/boost@lists.boost.org/msg03318.html
311 #define MIRA_MAKE_SEQ(size, rel) MIRA_MAKE_SEQ_D(size, rel)
312 #define MIRA_MAKE_SEQ_D(size, rel) \
313  BOOST_PP_CAT( \
314  MIRA_MAKE_SEQ_A_ ## size rel, \
315  0X0 \
316  )() \
317 
318 
319 // size 1
320 #define MIRA_MAKE_SEQ_A_1(a) ((a)) MIRA_MAKE_SEQ_B_1
321 #define MIRA_MAKE_SEQ_B_1(a) ((a)) MIRA_MAKE_SEQ_A_1
322 
323 #define MIRA_MAKE_SEQ_A_10X0()
324 #define MIRA_MAKE_SEQ_B_10X0()
325 
326 // size 2
327 #define MIRA_MAKE_SEQ_A_2(a, b) ((a, b)) MIRA_MAKE_SEQ_B_2
328 #define MIRA_MAKE_SEQ_B_2(a, b) ((a, b)) MIRA_MAKE_SEQ_A_2
329 
330 #define MIRA_MAKE_SEQ_A_20X0()
331 #define MIRA_MAKE_SEQ_B_20X0()
332 
333 // size 3
334 #define MIRA_MAKE_SEQ_A_3(a, b, c) ((a, b, c)) MIRA_MAKE_SEQ_B_3
335 #define MIRA_MAKE_SEQ_B_3(a, b, c) ((a, b, c)) MIRA_MAKE_SEQ_A_3
336 
337 #define MIRA_MAKE_SEQ_A_30X0()
338 #define MIRA_MAKE_SEQ_B_30X0()
339 
340 // size 4
341 #define MIRA_MAKE_SEQ_A_4(a, b, c, d) ((a, b, c, d)) MIRA_MAKE_SEQ_B_4
342 #define MIRA_MAKE_SEQ_B_4(a, b, c, d) ((a, b, c, d)) MIRA_MAKE_SEQ_A_4
343 
344 #define MIRA_MAKE_SEQ_A_40X0()
345 #define MIRA_MAKE_SEQ_B_40X0()
346 
347 // size 5
348 #define MIRA_MAKE_SEQ_A_5(a, b, c, d, e) ((a, b, c, d, e)) MIRA_MAKE_SEQ_B_5
349 #define MIRA_MAKE_SEQ_B_5(a, b, c, d, e) ((a, b, c, d, e)) MIRA_MAKE_SEQ_A_5
350 
351 #define MIRA_MAKE_SEQ_A_50X0()
352 #define MIRA_MAKE_SEQ_B_50X0()
353 
354 // size 6
355 #define MIRA_MAKE_SEQ_A_6(a, b, c, d, e, f) ((a, b, c, d, e, f)) MIRA_MAKE_SEQ_B_6
356 #define MIRA_MAKE_SEQ_B_6(a, b, c, d, e, f) ((a, b, c, d, e, f)) MIRA_MAKE_SEQ_A_6
357 
358 #define MIRA_INTERNAL_PRINT_TOKEN(TOKEN) #TOKEN
359 
360 #define MIRA_DO_NOTHING(Sequence,StartId)
361 
362 #define MIRA_INTERNAL_NAMESPACE_FOLD(r,data,t) \
363  t::data
364 
365 #define MIRA_INTERNAL_CONC_NAMESPACE_IMPL(Sequence, StartId) \
366  BOOST_PP_SEQ_FOLD_RIGHT(MIRA_INTERNAL_NAMESPACE_FOLD,,BOOST_PP_SEQ_REST_N(StartId,Sequence))
367 
368 #define MIRA_INTERNAL_CONC_NAMESPACE(Sequence,StartId) \
369  /* check if namespace size is greater zero and delay evaluation */ \
370  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( BOOST_PP_SEQ_REST_N( StartId, Sequence) ), \
371  /* length of namespace is greater zero */ \
372  MIRA_INTERNAL_CONC_NAMESPACE_IMPL \
373  /* we do not have a namespace -> do nothing */ \
374  , MIRA_DO_NOTHING )(Sequence, StartId)
375 
376 #define MIRA_INTERNAL_TEMPLATE_CLASS_REGISTER( r, Args, TmplSpec) \
377  /* Args(0) - contains the Class itself */ \
378  /* Args(1) - number of parents k */ \
379  /* Args(2) - number of template parameters */ \
380  /* Args(3) - address n of first namespace token in sequence Args */ \
381  /* Args(4 -- 4+k) - parents */ \
382  /* Args(n -- end) - namespace */ \
383  MIRA_REGISTRAR( MIRA_PPARAM( mira::FactoryRegisterClass< \
384  /* the folding process adds the namespace, if the namesapce sequence*/ \
385  /* length is greater than zero (with delayed evaluation) */ \
386  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( BOOST_PP_SEQ_REST_N( \
387  BOOST_PP_SEQ_ELEM(3,Args),Args) ), \
388  /* length of namespace is greater zero */ \
389  MIRA_INTERNAL_CONC_NAMESPACE_IMPL \
390  /* we do not have a namespace -> do nothing */ \
391  , MIRA_DO_NOTHING )( Args, BOOST_PP_SEQ_ELEM(3,Args) ) \
392  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR( BOOST_PP_SEQ_ELEM(2,Args), TmplSpec)>, \
393  BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_SUBSEQ(Args,4,BOOST_PP_SEQ_ELEM(1,Args)))> ) ) \
394 
395 
396 #define MIRA_INTERNAL_TEMPLATE_CLASS_STATIC( r, Args, TmplSpec) \
397  /* Args(0) contains the Class itself */ \
398  /* Args(1) contains the number of template parameters */ \
399  template<> mira::TClass<\
400  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >& \
401  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)>::_staticClassObject( \
402  std::string const& identifier, \
403  std::string const& name, \
404  bool libLoaded) { \
405  static mira::TemplateClass<BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> > \
406  sClass(identifier, name, libLoaded); \
407  return sClass; \
408  } \
409 
410 
411 #define MIRA_TMPL_SPEC_CONCAT(r, data, i, elem) "," BOOST_PP_STRINGIZE(elem)
412 
413 #define TAIL_NAME( Seq ) \
414  BOOST_PP_SEQ_FOR_EACH_I( MIRA_TMPL_SPEC_CONCAT, , Seq)
415 
416 #define MIRA_INTERNAL_TEMPLATE_IDENTIFIER( r, Args, TmplSpec) \
417  /* Args(0) contains the Class itself */ \
418  /* Args(1) contains the number of template parameters */ \
419  /* Args(2-n) contains the namespace */ \
420  template<> \
421  /* the folding process adds the namespace */ \
422  std::string const& TemplateClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
423  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getIdentifier() const { \
424  /* we should use a combination of the generic and the specialized */ \
425  /* here since the generic string should include the namespace.*/ \
426  static std::string tIdent = replaceTemplateGeneric( \
427  TClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
428  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getIdentifier(), \
429  "<" \
430  BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_SEQ_ELEM(1,Args),TmplSpec))) \
431  /* use for_each_i here since recursion of fore_each is not allowed */ \
432  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))) \
433  ">" ); \
434  return tIdent; \
435  } \
436  \
437  template<> \
438  /* the folding process adds the namespace */ \
439  std::string const& TemplateClass<MIRA_INTERNAL_CONC_NAMESPACE(Args,2) \
440  BOOST_PP_SEQ_ELEM(0,Args)<BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_SEQ_ELEM(1,Args), TmplSpec)> >::getName() const { \
441  static std::string tName = mira_stripNameFromIdentifier( \
442  getIdentifier() ); \
443  return tName; \
444  } \
445 
446 
460 #define MIRA_TEMPLATE_CLASS_REGISTER( Namespace, Class, TmplSpec, ... ) \
461  MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, 1, MIRA_MAKE_SEQ(1,TmplSpec), __VA_ARGS__ )
462 
475 #define MIRA_VARTEMPLATE_CLASS_REGISTER( Namespace, Class, NumTmplPrm, TmplSpec, ... ) \
476  MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, NumTmplPrm, MIRA_MAKE_SEQ(NumTmplPrm,TmplSpec), __VA_ARGS__ )
477 
479 
480 #define MIRA_TMPL_SIG_FROM_SEQ( NumTmplPrm, SeqId, Sequence )\
481  BOOST_PP_TUPLE_REM_CTOR( NumTmplPrm, BOOST_PP_SEQ_ELEM(SeqId,Sequence) )
482 
483 #define MIRA_TEMPLATE_CLASS_REGISTER_IMPL( Namespace, Class, NumTmplPrm, TmplSpec, ... ) \
484  /* generate error message if macro is not used in global namespace */ \
485  template <> int \
486  ________________________________PLEASE_USE_THE__MIRA_TEMPLATE_CLASS_REGISTER__MACRO_IN_GLOBAL_NAMESPACE_ONLY________________________________\
487  <MIRA_INTERNAL_CONC_NAMESPACE(Namespace,0)Class \
488  <MIRA_TMPL_SIG_FROM_SEQ(NumTmplPrm,0,TmplSpec)> >::FOR_CLASS() { return 0; } \
489  /* the following lines build up a sequence for the internal register macro*/\
490  /* structure: (Class)(Number of Parents)(Address of first namespace token */\
491  /* in the sequence)(Parents as sequence)(Namespace as sequence) */ \
492  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_CLASS_REGISTER, \
493  (Class) \
494  (MIRA_VA_NUM_ARGS(__VA_ARGS__))(NumTmplPrm)(BOOST_PP_ADD(MIRA_VA_NUM_ARGS(__VA_ARGS__),4))\
495  BOOST_PP_TUPLE_TO_SEQ(MIRA_VA_NUM_ARGS(__VA_ARGS__),(__VA_ARGS__)) \
496  Namespace,TmplSpec) \
497  \
498  /* we can only specialize the the template in the corresponding namespace */\
499  /* check if length of namespace is greater than zero */ \
500  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( Namespace ), \
501  /* length of namespace is greater zero */ \
502  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_OPEN_NAMESPACE,~,Namespace) \
503  /* length of namespace is zero -> do nothing */ \
504  , ) \
505  /* we have to combine all parameters in a boost pp sequence in order */ \
506  /* to pass them to the internal macro */ \
507  /* Register the class at the factory */ \
508  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_CLASS_STATIC, \
509  (Class)(NumTmplPrm), TmplSpec) \
510  /* check if length of namespace is greater than zero */ \
511  BOOST_PP_IF( BOOST_PP_SEQ_SIZE( Namespace ), \
512  /* length of namespace is greater zero */ \
513  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_CLOSE_NAMESPACE,~,Namespace) \
514  /* length of namespace is zero -> do nothing */ \
515  , ) \
516  \
517  namespace mira { \
518  /* Specialize the functions to obtain the template identifiers */ \
519  BOOST_PP_SEQ_FOR_EACH(MIRA_INTERNAL_TEMPLATE_IDENTIFIER, \
520  (Class)(NumTmplPrm)Namespace,TmplSpec) \
521  }
522 
524 
526 
527 } // namespace
528 
529 #endif /* _MIRA_FACTORYMACROS_H_ */
530 
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:88
std::string replaceTemplateGeneric(std::string const &genericIdent, std::string const &specialIdent)
Definition: FactoryMacros.h:276