MIRA
TClass.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 
48 #ifndef _MIRA_TCLASS_H_
49 #define _MIRA_TCLASS_H_
50 
51 #include <string>
52 
53 #include <utils/HasMember.h>
54 #include <utils/Foreach.h>
55 #include <factory/Class.h>
57 
58 namespace mira {
59 
61 
62 MIRA_MEMBER_DETECTOR( mNoPublicDefaultConstructor );
63 
64 // *****************************************************************************
65 // *** TClass
66 // *****************************************************************************
67 
74 template<typename CLASS>
75 class TClass: public Class
76 {
77  friend class ClassFactory;
78 public:
84  TClass( std::string const& identifier,
85  std::string const& name,
86  bool libLoaded );
87 
92  virtual int getTypeId() const;
93 
98  virtual Typename getTypename() const;
99 
105  CLASS* newInstance() const;
106 
111  virtual Object* newInstance( int paramCount, ... ) const;
112 
118  CLASS* newInstance( std::string const& childIdentifier ) const;
119 
125  Object* newInstance( std::string const& childIdentifier,
126  int paramCount, ... ) const;
127 
131  virtual bool isAbstract() const;
132 
133 protected:
134 
139  Object* newVAInstance( std::string const& childIdentifier,
140  int paramCount,
141  std::va_list ap ) const;
142 
147  Object* newVAInstance( int paramCount, std::va_list ap ) const;
148 
149 private:
150  TClass( )
151  {
152  }
153 
154 };
155 
156 // *****************************************************************************
157 // *** TClass implementation
158 // *****************************************************************************
159 
160 template<typename CLASS>
161 inline TClass<CLASS>::TClass( std::string const& identifier,
162  std::string const& name, bool libLoaded ) :
163  Class( identifier, name, libLoaded )
164 {
165  // add meta info
166  CLASS::addMetaInfo( mMetaInfo );
167 }
168 
169 template<typename CLASS>
170 inline int TClass<CLASS>::getTypeId() const
171 {
172  return typeId<CLASS>();
173 }
174 
175 template<typename CLASS>
177 {
178  return typeName<CLASS>();
179 }
180 
181 template<typename CLASS>
182 inline bool TClass<CLASS>::isAbstract() const
183 {
184  return std::is_abstract<CLASS>::value;
185 }
186 
187 
188 template<typename CLASS>
190 {
191  // check if the class is abstract and / or do have a default constructor
192  // since the check for the default constructor fails on some compilers,
193  // we have to check for the mNoPublicDefaultConstructor member additionally
194  typedef typename
195  boost::mpl::eval_if<std::is_abstract<CLASS>,
196  boost::mpl::identity<ClassFactoryAbstractClassBuilder>,
197  // else
199  boost::mpl::identity< ClassFactoryDefaultConstClassBuilder >,
200  boost::mpl::identity< ClassFactoryNoDefaultConstClassBuilder > >
201  >::type ClassType;
202 
203  return ClassType::template invoke<CLASS>( );
204 }
205 
206 template<typename CLASS>
207 Object* TClass<CLASS>::newInstance( int paramCount, ... ) const
208 {
209  std::va_list ap;
210  va_start(ap, paramCount);
211  return newVAInstance( paramCount, ap);
212 }
213 
214 template<typename CLASS>
215 CLASS* TClass<CLASS>::newInstance( std::string const& childIdentifier ) const
216 {
217  // handle the case that someone wants to create an instance of US.
218  // obtain identifier by function since it might be different from
219  // mIdentifier (template classes)
220  if( childIdentifier == getIdentifier() )
221  return newInstance();
222  // check if the desired object is a registered derived child
223  if ( mDerivedChildren.find( childIdentifier ) ==
224  mDerivedChildren.end() ) {
225  MIRA_THROW( XFactoryUnknown, "Unknown class identifier ("
226  + childIdentifier +") calling newInstance on " + getIdentifier()
227  + " !" );
228  }
229  Object* tObject = mDerivedChildren.find( childIdentifier )->second.newInstance();
230  if ( !tObject ) {
231  MIRA_THROW( XFactoryLogical, "Class creation failed (" + childIdentifier
232  + ") calling newInstance on " + getIdentifier() + "!" );
233  }
234  // try to cast object to desired class
235  return mira_factoryDynamicCast<CLASS>( tObject );
236 }
237 
238 template<typename CLASS>
239 Object* TClass<CLASS>::newInstance( std::string const& childIdentifier,
240  int paramCount, ... ) const
241 {
242  std::va_list ap;
243  va_start(ap, paramCount);
244 
245  return newVAInstance( childIdentifier, paramCount, ap );
246 }
247 
248 template<typename CLASS>
249 Object* TClass<CLASS>::newVAInstance( std::string const& childIdentifier,
250  int paramCount,
251  std::va_list ap ) const
252 {
253  // obtain identifier by function since it might be different from
254  // mIdentifier (template classes)
255  if(childIdentifier==getIdentifier())
256  return newVAInstance(paramCount, ap);
257  // check if the desired object is a registered derived child
258  if ( mDerivedChildren.find( childIdentifier ) ==
259  mDerivedChildren.end() ) {
260  MIRA_THROW( XFactoryUnknown, "Unknown class identifier ("
261  + childIdentifier + ") calling newInstance on " + getIdentifier()
262  + "!" );
263  }
264 
265  Object* tObject = mDerivedChildren.find( childIdentifier )->second
266  .newVAInstance(paramCount, ap);
267  if ( !tObject ) {
268  MIRA_THROW( XFactoryLogical, "Class creation failed (" + childIdentifier
269  + ") calling newInstance on " + getIdentifier() + "!" );
270  }
271  return tObject;
272 }
273 
274 template<typename CLASS>
275 Object* TClass<CLASS>::newVAInstance( int paramCount, std::va_list ap ) const
276 {
277  // Check if we should use the normal createClass template or the special
278  // instantiation for classes with abstract functions
279  typedef typename boost::mpl::eval_if<std::is_abstract<CLASS>,
280  boost::mpl::identity<ClassFactoryAbstractClassBuilder>,
281  boost::mpl::identity<ClassFactoryDefaultConstClassBuilder>
282  >::type ClassType;
283 
284  switch(paramCount){
285  case 0:
286  return newInstance();
287  case 1:
288  return ClassType::template invoke<1,CLASS>( ap);
289  case 2:
290  return ClassType::template invoke<2,CLASS>( ap);
291  case 3:
292  return ClassType::template invoke<3,CLASS>( ap);
293  case 4:
294  return ClassType::template invoke<4,CLASS>( ap);
295  default:
296  MIRA_THROW( XFactoryLogical, "Invalid number of arguments for "
297  "constructor (" + std::to_string((uint64)paramCount) + " arguments for "
298  + getIdentifier() + ")!");
299  }
300  return NULL;
301 }
302 
304 
305 } // namespace
306 
307 #endif /* _MIRA_TCLASS_H_ */
308 
Macro for iterating over all elements in a container.
$Definition of the Class which supports some kind of class reflection and acts like a class factory$...
What should i say, the class factory.
Definition: Factory.h:88
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
virtual int getTypeId() const
Return unique id for the class.
Definition: TClass.h:170
std::string Typename
Definition: Typename.h:60
Class object which supports some kind of class reflection.
Definition: Class.h:97
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:82
$short description$.
CLASS * newInstance() const
Return a new instance of the class associated with the class object.
Definition: TClass.h:189
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
The object class acts as a generic base class for classes which should be used with the classFactory...
Definition: Object.h:144
virtual bool isAbstract() const
Return true if the associated class is abstract.
Definition: TClass.h:182
MIRA_MEMBER_DETECTOR(mNoPublicDefaultConstructor)
Object * newVAInstance(std::string const &childIdentifier, int paramCount, std::va_list ap) const
Return a new instance of the child class with the given identifier.
Definition: TClass.h:249
The TClass object is the implementation of the class class for classes which are available since the ...
Definition: TClass.h:75
Macros for checking the existence of class members.
virtual Typename getTypename() const
Returns the platform independent C++ typename of the class.
Definition: TClass.h:176