MRPT  2.0.2
CObject.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
13 #include <mrpt/typemeta/static_string.h> // literal()
14 #include <functional>
15 #include <memory>
16 #include <vector>
17 
18 namespace mrpt
19 {
20 namespace rtti
21 {
22 /** @name RTTI classes and functions for polymorphic hierarchies
23  @{ */
24 class CObject;
25 
26 /** A structure that holds runtime class type information. Use
27  * CLASS_ID(<class_name>) to get a reference to the class_name's TRuntimeClassId
28  * descriptor.
29  * \ingroup mrpt_rtti_grp
30  */
32 {
34  const char* className;
35  /** Create an object of the related class, or nullptr if it is virtual. */
36  std::function<std::shared_ptr<CObject>(void)> ptrCreateObject;
37  /** Gets the base class runtime id. */
38  const TRuntimeClassId* (*getBaseClass)();
39 
40  // Operations
42  bool derivedFrom(const TRuntimeClassId* pBaseClass) const;
43  bool derivedFrom(const char* pBaseClass_name) const;
44 };
45 
46 /** Register a class into the MRPT internal list of "CObject" descendents.
47  * Used internally in the macros DEFINE_SERIALIZABLE, etc...
48  * \sa getAllRegisteredClasses
49  */
50 void registerClass(const mrpt::rtti::TRuntimeClassId* pNewClass);
51 
52 /** Mostly for internal use within mrpt sources, to handle exceptional cases
53  * with multiple serialization names for backward compatibility
54  * (CMultiMetricMaps, CImage,...)
55  */
57  const char* customName, const TRuntimeClassId* pNewClass);
58 
59 /** Returns a list with all the classes registered in the system through
60  * mrpt::rtti::registerClass.
61  * \sa registerClass, findRegisteredClass
62  */
63 std::vector<const mrpt::rtti::TRuntimeClassId*> getAllRegisteredClasses();
64 
65 /** Like getAllRegisteredClasses(), but filters the list to only include
66  * children clases of a given base one.
67  * \sa getAllRegisteredClasses(), getAllRegisteredClassesChildrenOf() */
68 std::vector<const TRuntimeClassId*> getAllRegisteredClassesChildrenOf(
69  const TRuntimeClassId* parent_id);
70 
71 /** Return info about a given class by its name, or nullptr if the class is not
72  * registered.
73  *
74  * The list of registered "namespaces::class_name" will be looked up first. If
75  * no match is found, **and** `allow_ignore_namespace=true`, then a second
76  * search will be performed looking for a match of the class name without the
77  * namespace part. Note that this is enabled by default since namespaces were
78  * not used while serializing classes in MRPT older than v2.0, so this option
79  * allows reading from older datasets transparently. It could be set to false if
80  * it is ensured that only mrpt2 datasets will be read.
81  *
82  * \param[in] className The name of the class to look up
83  * \param[i] allow_ignore_namespace See discussion above
84  *
85  * \sa registerClass, getAllRegisteredClasses
86  */
88  const std::string& className, const bool allow_ignore_namespace = true);
89 
90 template <typename T>
92 {
93  static constexpr const mrpt::rtti::TRuntimeClassId* get()
94  {
95  return &T::GetRuntimeClassIdStatic();
96  }
97 };
98 //(A specialization for variant's monostate is provided in CArchive.h)
99 
100 /** Access to runtime class ID for a defined class name.
101  */
102 #define CLASS_ID(T) mrpt::rtti::CLASS_ID_impl<T>::get()
103 // Convert these
104 #define CLASS_ID_TEMPLATE(class_name, T) mrpt::rtti::CLASS_ID_impl<T>::get()
105 #define CLASS_ID_NAMESPACE(class_name, namespaceName) \
106  mrpt::rtti::CLASS_ID_impl<namespaceName::class_name>::get()
107 
108 template <typename T>
110 {
111  template <typename REF>
112  static bool check(const REF& p)
113  {
114  return p.GetRuntimeClass() == CLASS_ID_impl<T>::get();
115  }
116 };
117 
118 namespace internal
119 {
120 template <bool is_copy_ctrtible>
121 struct CopyCtor;
122 template <>
123 struct CopyCtor<true>
124 {
125  template <typename T>
126  static T* clone(const T& o)
127  {
128  return new T(o);
129  }
130 };
131 template <>
132 struct CopyCtor<false>
133 {
134  template <typename T>
135  static T* clone(const T& o)
136  {
137  throw std::runtime_error(
138  "clone(): Attempt to call copy ctor of non copy-constructible "
139  "class.");
140  }
141 };
142 } // namespace internal
143 
144 /** True if the given reference to object (derived from mrpt::rtti::CObject) is
145  * of the given class. */
146 #define IS_CLASS(obj, class_name) \
147  mrpt::rtti::IS_CLASS_impl<class_name>::check(obj)
148 
149 /** True if the given reference to object (derived from mrpt::rtti::CObject) is
150  * an instance of the given class OR any of its derived classes. */
151 #define IS_DERIVED(obj, class_name) \
152  ((obj).GetRuntimeClass()->derivedFrom(CLASS_ID(class_name)))
153 
154 /** Virtual base to provide a compiler-independent RTTI system.
155  *
156  * Each class named `Foo` will have associated smart pointer types:
157  * - `Foo::Ptr` => `std::shared_ptr<Foo>` (the most commonly-used one)
158  * - `Foo::ConstPtr` => `std::shared_ptr<const Foo>`
159  * - `Foo::UniquePtr` => `std::unique_ptr<Foo>`
160  * - `Foo::ConstUniquePtr` => `std::unique_ptr<const Foo>`
161  *
162  * It is recommended to use MRPT-defined `std::make_shared<>` instead
163  * of `std::make_shared<>` to create objects, to avoid memory alignment
164  * problems caused by classes containing Eigen vectors or matrices. Example:
165  * \code
166  * Foo::Ptr o = std::make_shared<Foo>();
167  * \endcode
168  * Or using the shorter auxiliary static method `::Create()` for conciseness or
169  * to keep compatibility with MRPT 1.5.* code bases:
170  * \code
171  * Foo::Ptr o = Foo::Create();
172  * \endcode
173  * If a special memory allocator is needed, use `Foo::CreateAlloc(alloc,...);`.
174  * \sa mrpt::rtti::CObject
175  * \ingroup mrpt_rtti_grp
176  */
177 class CObject
178 {
179  protected:
182 
183  public:
186  using UniquePtr = std::unique_ptr<CObject>;
187  using ConstUniquePtr = std::unique_ptr<const CObject>;
189  /** Returns information about the class of an object in runtime. */
191  {
192  return CLASS_ID(CObject);
193  }
194 
195  /** Makes a deep copy of the object and returns a smart pointer to it */
197 
198  /** Returns a deep copy (clone) of the object, indepently of its class. */
199  virtual CObject* clone() const = 0;
200 
201  virtual ~CObject() = default;
202 }; // End of class def.
203 
205 {
206  return mrpt::rtti::CObject::Ptr(this->clone());
207 }
208 
209 /** This declaration must be inserted in all CObject classes definition, within
210  * the class declaration. */
211 #define DEFINE_MRPT_OBJECT(class_name, NameSpace) \
212  /*! @name RTTI stuff */ \
213  /*! @{ */ \
214  protected: \
215  static const mrpt::rtti::TRuntimeClassId* _GetBaseClass(); \
216  static const mrpt::rtti::TRuntimeClassId runtimeClassId; \
217  \
218  public: \
219  /*! A type for the associated smart pointer */ \
220  using Ptr = std::shared_ptr<NameSpace::class_name>; \
221  using ConstPtr = std::shared_ptr<const NameSpace::class_name>; \
222  using UniquePtr = std::unique_ptr<NameSpace::class_name>; \
223  using ConstUniquePtr = std::unique_ptr<const NameSpace::class_name>; \
224  static constexpr const char* className = #NameSpace "::" #class_name; \
225  static constexpr auto getClassName() \
226  { \
227  return mrpt::typemeta::literal(#NameSpace "::" #class_name); \
228  } \
229  static const mrpt::rtti::TRuntimeClassId& GetRuntimeClassIdStatic(); \
230  virtual const mrpt::rtti::TRuntimeClassId* GetRuntimeClass() \
231  const override; \
232  virtual mrpt::rtti::CObject* clone() const override; \
233  static std::shared_ptr<CObject> CreateObject(); \
234  template <typename... Args> \
235  static Ptr Create(Args&&... args) \
236  { \
237  return std::make_shared<class_name>(std::forward<Args>(args)...); \
238  } \
239  template <typename Alloc, typename... Args> \
240  static Ptr CreateAlloc(const Alloc& alloc, Args&&... args) \
241  { \
242  return std::allocate_shared<class_name>( \
243  alloc, std::forward<Args>(args)...); \
244  } \
245  template <typename... Args> \
246  static UniquePtr CreateUnique(Args&&... args) \
247  { \
248  return std::make_unique<class_name>(std::forward<Args>(args)...); \
249  } \
250  /*! @} */ \
251  public:
252 
253 #define INTERNAL_IMPLEMENTS_MRPT_OBJECT( \
254  class_name, base, NameSpace, class_registry_name) \
255  mrpt::rtti::CObject::Ptr NameSpace::class_name::CreateObject() \
256  { \
257  return std::static_pointer_cast<CObject>( \
258  std::make_shared<NameSpace::class_name>()); \
259  } \
260  const mrpt::rtti::TRuntimeClassId* NameSpace::class_name::_GetBaseClass() \
261  { \
262  return CLASS_ID(base); \
263  } \
264  const mrpt::rtti::TRuntimeClassId& \
265  NameSpace::class_name::GetRuntimeClassIdStatic() \
266  { \
267  return NameSpace::class_name::runtimeClassId; \
268  } \
269  const mrpt::rtti::TRuntimeClassId NameSpace::class_name::runtimeClassId = \
270  {class_registry_name, NameSpace::class_name::CreateObject, \
271  &class_name::_GetBaseClass}; \
272  const mrpt::rtti::TRuntimeClassId* \
273  NameSpace::class_name::GetRuntimeClass() const \
274  { \
275  return CLASS_ID_NAMESPACE(class_name, NameSpace); \
276  } \
277  mrpt::rtti::CObject* NameSpace::class_name::clone() const \
278  { \
279  return mrpt::rtti::internal::CopyCtor<std::is_copy_constructible< \
280  NameSpace::class_name>::value>::clone(*this); \
281  }
282 
283 /** Must be added to all CObject-derived classes implementation file.
284  * This registers class ns1::Foo as "ns1::Foo".
285  */
286 #define IMPLEMENTS_MRPT_OBJECT(class_name, base, NameSpace) \
287  INTERNAL_IMPLEMENTS_MRPT_OBJECT( \
288  class_name, base, NameSpace, #NameSpace "::" #class_name)
289 
290 /** This declaration must be inserted in virtual CObject classes
291  * definition:
292  */
293 #define DEFINE_VIRTUAL_MRPT_OBJECT(class_name) \
294  /*! @name RTTI stuff */ \
295  /*! @{ */ \
296  protected: \
297  static const mrpt::rtti::TRuntimeClassId* _GetBaseClass(); \
298  static const mrpt::rtti::TRuntimeClassId runtimeClassId; \
299  \
300  public: \
301  using Ptr = std::shared_ptr<class_name>; \
302  using ConstPtr = std::shared_ptr<const class_name>; \
303  virtual const mrpt::rtti::TRuntimeClassId* GetRuntimeClass() \
304  const override; \
305  static const mrpt::rtti::TRuntimeClassId& GetRuntimeClassIdStatic(); \
306  /*! @} */
307 
308 /** This must be inserted as implementation of some required members for
309  * virtual CObject classes:
310  */
311 #define INTERNAL_IMPLEMENTS_VIRTUAL_MRPT_OBJECT( \
312  class_name, base_name, NS, registered_name) \
313  const mrpt::rtti::TRuntimeClassId* NS::class_name::_GetBaseClass() \
314  { \
315  return CLASS_ID(base_name); \
316  } \
317  const mrpt::rtti::TRuntimeClassId NS::class_name::runtimeClassId = { \
318  registered_name, nullptr, &NS::class_name::_GetBaseClass}; \
319  const mrpt::rtti::TRuntimeClassId* NS::class_name::GetRuntimeClass() const \
320  { \
321  return CLASS_ID(class_name); \
322  } \
323  const mrpt::rtti::TRuntimeClassId& \
324  NS::class_name::GetRuntimeClassIdStatic() \
325  { \
326  return NS::class_name::runtimeClassId; \
327  }
328 
329 #define IMPLEMENTS_VIRTUAL_MRPT_OBJECT(class_name, base, NS) \
330  INTERNAL_IMPLEMENTS_VIRTUAL_MRPT_OBJECT( \
331  class_name, base, NS, #NS "::" #class_name)
332 
333 /** Register all pending classes - to be called just before
334  * de-serializing an object, for example. After calling this method,
335  * pending_class_registers_modified is set to false until
336  * pending_class_registers() is invoked.
337  */
339 
340 /** Creates an object given by its registered name.
341  * \sa findRegisteredClass(), registerClass() */
342 mrpt::rtti::CObject::Ptr classFactory(const std::string& className);
343 
344 /** @} */ // end of RTTI
345 
346 } // namespace rtti
347 
348 /** Converts a polymorphic smart pointer Base::Ptr to Derived::Ptr, in a
349  * way compatible with MRPT >=1.5.4 and MRPT 2.x series.
350  * \ingroup mrpt_rtti_grp
351  */
352 template <typename CAST_TO>
353 struct ptr_cast
354 {
355  template <typename CAST_FROM_PTR>
356  static typename CAST_TO::Ptr from(const CAST_FROM_PTR& ptr)
357  {
358  return std::dynamic_pointer_cast<CAST_TO>(ptr);
359  }
360 };
361 
362 } // namespace mrpt
virtual ~CObject()=default
std::shared_ptr< CObject > createObject() const
Definition: CObject.cpp:79
void registerAllPendingClasses()
Register all pending classes - to be called just before de-serializing an object, for example...
std::unique_ptr< CObject > UniquePtr
Definition: CObject.h:186
std::vector< const TRuntimeClassId * > getAllRegisteredClassesChildrenOf(const TRuntimeClassId *parent_id)
Like getAllRegisteredClasses(), but filters the list to only include children clases of a given base ...
A structure that holds runtime class type information.
Definition: CObject.h:31
Converts a polymorphic smart pointer Base::Ptr to Derived::Ptr, in a way compatible with MRPT >=1...
Definition: CObject.h:353
Virtual base to provide a compiler-independent RTTI system.
Definition: CObject.h:177
std::unique_ptr< const CObject > ConstUniquePtr
Definition: CObject.h:187
static constexpr const mrpt::rtti::TRuntimeClassId * get()
Definition: CObject.h:93
#define CLASS_ID(T)
Access to runtime class ID for a defined class name.
Definition: CObject.h:102
virtual CObject * clone() const =0
Returns a deep copy (clone) of the object, indepently of its class.
const char * className
Definition: CObject.h:34
static bool check(const REF &p)
Definition: CObject.h:112
static T * clone(const T &o)
Definition: CObject.h:135
virtual const mrpt::rtti::TRuntimeClassId * GetRuntimeClass() const
Returns information about the class of an object in runtime.
Definition: CObject.h:190
std::function< std::shared_ptr< CObject >void)> ptrCreateObject
Create an object of the related class, or nullptr if it is virtual.
Definition: CObject.h:36
const TRuntimeClassId * findRegisteredClass(const std::string &className, const bool allow_ignore_namespace=true)
Return info about a given class by its name, or nullptr if the class is not registered.
A wrapper class for pointers that can be safely copied with "=" operator without problems.
Definition: safe_pointers.h:71
void registerClassCustomName(const char *customName, const TRuntimeClassId *pNewClass)
Mostly for internal use within mrpt sources, to handle exceptional cases with multiple serialization ...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
static const mrpt::rtti::TRuntimeClassId & GetRuntimeClassIdStatic()
Definition: CObject.cpp:19
static mrpt::rtti::TRuntimeClassId * _GetBaseClass()
Definition: CObject.cpp:104
static T * clone(const T &o)
Definition: CObject.h:126
mrpt::rtti::CObject::Ptr classFactory(const std::string &className)
Creates an object given by its registered name.
Definition: CObject.cpp:108
bool derivedFrom(const TRuntimeClassId *pBaseClass) const
Definition: CObject.cpp:24
static CAST_TO::Ptr from(const CAST_FROM_PTR &ptr)
Definition: CObject.h:356
void registerClass(const mrpt::rtti::TRuntimeClassId *pNewClass)
Register a class into the MRPT internal list of "CObject" descendents.
static const mrpt::rtti::TRuntimeClassId runtimeClassId
Definition: CObject.h:181
std::vector< const mrpt::rtti::TRuntimeClassId * > getAllRegisteredClasses()
Returns a list with all the classes registered in the system through mrpt::rtti::registerClass.
std::shared_ptr< CObject > Ptr
Definition: CObject.h:184
mrpt::rtti::CObject::Ptr duplicateGetSmartPtr() const
Makes a deep copy of the object and returns a smart pointer to it.
Definition: CObject.h:204



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020