MIRA
RecursiveMemberReflector.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_RECURSIVEMEMBERREFLECTOR_H_
48 #define _MIRA_RECURSIVEMEMBERREFLECTOR_H_
49 
50 #include <type_traits>
51 
52 #include <error/LoggingCore.h>
53 
54 #include <factory/Factory.h>
55 
56 #include <serialization/Accessor.h>
57 
61 
62 #include <serialization/Array.h>
63 
68 
70 
71 #include <serialization/VoidCast.h>
72 
73 #include <utils/Singleton.h>
74 #include <utils/ToString.h>
75 
76 namespace mira {
77 
79 
80 namespace serialization {
81 
83 
95 template <typename T, typename Reflector>
97  ReflectedAsPointer()= default;
98  bool value = false;
99 };
100 
101 template <typename T, typename Reflector>
104  LazySingleton<ReflectedAsPointer<T,Reflector>>::instance().value = true;
105  }
106 };
107 
109 
110 } // namespace
111 
116 MIRA_DEFINE_SERIALIZABLE_EXCEPTION(XMemberNotFound, XIO)
117 
118 
123 class XMemberNotFound_NoDefault : public XMemberNotFound
124 {
126 protected:
127  friend class ClassFactoryDefaultConstClassBuilder;
129 
130 public:
132  XMemberNotFound(ex) {}
133 
134  void raise(bool recursive = false) override
135  {
136  // The exception object is copy-initialized from *this.
137  throw *this;
138  }
139 };
140 
142 
232 template <typename Derived>
234 {
236 public:
237 
240  mCurrentMemberMeta(nullptr) {}
241 
242 protected:
243 
249  static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME = "@value";
250 
251 public:
252 
257 
267  template<typename T>
268  void atomic(T& member) {}
269 
280  template<typename T>
281  void enumeration(T& member) {
282  if(Derived::isReadOnly::value) {
283  auto val = static_cast<int32>(member);
284  this->This()->atomic(val);
285  } else {
286  int32 val;
287  this->This()->atomic(val);
288  member = static_cast<T>(val);
289  }
290  }
291 
300  template<typename T>
301  void object(T& member) {
302  this->This()->invoke(member); // invoke us recursively on the object
303  }
304 
310  template<typename T>
311  void collection(T& member) {
312  this->This()->object(member); // default impl calls object()
313  }
314 
315 
316  template<typename T>
317  void trackObject(T& member) {}
318 
324  template<typename T>
325  void pointer(T*& pointer)
326  {
327  // this will instantiate the SetReflectedAsPointer during startup
328  // which will set ReflectedAsPointer<T,Derived>::value to true,
329  // and mark that T was reflected as pointer by Derived at least once.
331  singleton::CreateStatic>::instance();
332 
333  if constexpr (std::is_base_of_v<mira::Object, T>) {
335  }
336  else if constexpr (std::is_abstract_v<T>) {
338  }
339  else {
341  }
342  }
343 
351  template<typename T>
352  void pointerNormal(T*& pointer, int typeId)
353  {
354  if (pointer != NULL) // delegate serialization of the actual object recursively
355  this->This()->invokePointerObject(*pointer);
356  }
357 
366  template<typename T>
368  {
369  if (pointer != NULL) { // delegate serialization of the actual object recursively
370 
371  try {
372  // obtain a special polymorph pointer serializer for the derived type
373  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
374 
375  typename OurRegistrar::ReflectorRef r =
376  OurRegistrar::instance().getPolymorphicPointerReflector(typeId);
377 
378  // deserialize the content recursively
379  r.invoke(*this->This(), serialization::void_upcast(pointer));
380  }
381  catch (XPolymorphicPointerReflectorNotRegistered&) {
382  const ReflectMemberMeta& meta = getCurrentMemberMeta();
383  const Class& c = pointer->getClass();
384  MIRA_THROW(XIO,
385  "Cannot reflect the polymorphic member pointer '"
386  << meta.name << "'. The class '" << c.getIdentifier()
387  << "' was not registered with this serializer '" << typeName<Derived>()
388  << "'"
389 #ifndef MIRA_REGISTER_LEGACY_SERIALIZERS
390  << " (Registration with legacy serializers must be explicitly enabled"
391  " by activating the option REGISTER_LEGACY_SERIALIZERS"
392  " [GlobalConfig, requires recompilation])";
393 #endif
394  );
395  }
396  }
397  }
398 
405  template<typename T>
407  {
408  if (pointer != NULL) // delegate serialization of the actual object recursively
409  this->This()->invokePointerObject(*pointer);
410  }
411 
413 
414 public:
415 
428  template<typename T>
429  static void registerClass()
430  {
431  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
432 
433  if(!OurRegistrar::isDestroyed())
434  OurRegistrar::instance().template registerClass<T>();
435  }
436 
447  template<typename T>
448  static void unregisterClass()
449  {
450  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
451  if(!OurRegistrar::isDestroyed())
452  OurRegistrar::instance().template unregisterClass<T>();
453  }
454 public:
455 
459  [[nodiscard]] const ReflectMemberMeta& getCurrentMemberMeta() const
460  {
461  assert(mCurrentMemberMeta!=NULL);
462  return *mCurrentMemberMeta;
463  }
464 
470  [[nodiscard]] const std::string& getCurrentMemberFullID() const
471  {
472  assert(this->usesHumanReadableIDs());
473  return mCurrentMemberFullID;
474  }
475 
476 public:
477 
483  template <typename T>
484  static bool isReflectedAsPointer() {
486  }
487 
488 protected:
490  template<typename T>
492  {
494  this->This()->trackObject(member);
495  }
496 
497  // The following structs implement different invoke methods for each of
498  // the member types (A1-3, B1-2, C). The member types are detected in
499  // the invoke method above which delegates to the invoke method
500  // of the correct struct below.
501 
502  template<typename T>
504  {
505  static_assert(sizeof(T) == 0, "Trying to reflect unknown type.");
506  }
507 
509  template<typename T>
511  {
512  this->This()->invokeTrackObject(member);
513  this->This()->atomic(member);
514  }
515 
517  template<typename T>
519  {
520  this->This()->invokeTrackObject(member);
521  this->This()->enumeration(member);
522  }
523 
525  template<typename T>
527  {
528  this->This()->invokeTrackObject(member);
529  std::size_t size = sizeof(member)
530  / (static_cast<const char*>(static_cast<const void*>(&member[1]))
531  - static_cast<const char*>(static_cast<const void*>(&member[0])));
532 
533  typedef typename std::remove_extent<T>::type ItemType;
534  serialization::Array<ItemType> array(member, size);
535  reflectCollection(array);
536  }
537 
539  template<typename T>
541  {
542  this->This()->invokeTrackObject(member);
543  typedef typename std::remove_cv<T>::type Type;
544  static_assert(!IsCollection<Type>::value,
545  "Trying to call reflectComplex<T>() with IsCollection<T> == true "
546  "- something is wrong.");
548  this->This()->invoke(member);
549  else
550  this->This()->object(member);
551  }
552 
554  template<typename T>
556  {
557  this->This()->invokeTrackObject(member);
558  typedef typename std::remove_cv<T>::type Type;
560  static_assert(!isTransparent::value,
561  "Trying to call reflectCollection<T>() with IsTransparentSerializable<T> == "
562  "true - something is wrong.");
563  this->This()->collection(member);
564  }
565 
567  template<typename T>
569  {
570  this->This()->pointer(member);
571  }
572 
573  // The following ReflectPointerXXX structs are used by our pointer() method
574 
576  template<typename T>
578  {
579  this->This()->pointerNormal(member, typeId<T>());
580  }
581 
583  template<typename T>
585  {
586  int typeId = -1;
587 
588  if (member != nullptr) {
589  // we have an object, so we can obtain its class information
590  const Class& c = member->getClass();
591  typeId = c.getTypeId();
592  }
593 
594  // call pointerPolymorphic()
595  this->This()->pointerPolymorphic(member, typeId);
596  }
597 
602  template<typename T>
604  {
605  this->This()->pointerAbstract(member, typeId<T>());
606  }
607 
611  template<typename T>
613  {
614  using Type = typename std::remove_cv<T>::type;
615  if constexpr (std::is_pointer_v<Type>) {
617  } // T is a pointer (Type C)
618  else if constexpr (IsAtomicSerializable<Type>::value) {
620  } // atomic (Type A1)
621  else if constexpr (std::is_class_v<Type>) {
622  if constexpr (IsCollection<Type>::value) {
624  } // T is a collection (Type B?c)
625  else {
627  } // T is a complex class (Type B1/B2)
628  }
629  else if constexpr (std::is_enum_v<Type>) {
631  } // enum (Type A2)
632  else if constexpr (std::is_array_v<Type>) {
634  } // T is no pointer, no class --> must be atomic or enum
635  else {
637  }
638  }
639 
640 public:
641 
652  template<typename T>
653  void invokeMember(T& member, const ReflectMemberMeta& meta)
654  {
655  this->This()->invokeMemberOverwrite(member, meta);
656  }
657 
664  template<typename T>
666  {
667  // store previous meta (it is restored at the end of this method
668  // and therefore implements a stack, where mCurrentMemberMeta is
669  // the top element in the stack)
670  const ReflectMemberMeta* prevMeta = mCurrentMemberMeta;
671 
672  // do the same to create a stack of the full human readable object
673  // id (however, only do it, if our final reflector supports human
674  // readable id's, otherwise skip this step since it hurts the
675  // performance
676  std::string prevFullID;
677  if(this->usesHumanReadableIDs()) {
678  prevFullID = mCurrentMemberFullID;
679 
680  // "push" new full id
681  if(mCurrentMemberFullID.empty()) {
682  if(meta.id==nullptr)
683  MIRA_THROW(XLogical, "Top-level member cannot be 'inline'. "
684  "It must have an ID != NULL!");
685  mCurrentMemberFullID=meta.id;
686  } else if(meta.id!=nullptr)
687  mCurrentMemberFullID = mCurrentMemberFullID + "." + meta.id;
688  }
689 
690  // "push" current meta (but only if member is not transparent, which is
691  // indicated by an id of NULL)
692  if(meta.id != nullptr)
693  mCurrentMemberMeta = &meta;
694 
695  // Choose the type of the member and select the
696  // correct ReflectXYZ struct for that type at compile type.
697  // Then call the invoke method of that struct.
698  // (The different structures and their invoke methods are defined
699  // above)
700  try
701  {
703  }
704  catch(...)
705  {
706  // "pop" our id
707  if(this->usesHumanReadableIDs())
708  mCurrentMemberFullID=prevFullID;
709  // "pop" our meta data stack.
710  mCurrentMemberMeta = prevMeta;
711  // and throw
712  throw;
713  }
714 
715  // "pop" our id
716  if(this->usesHumanReadableIDs())
717  mCurrentMemberFullID=prevFullID;
718  // "pop" our meta data stack.
719  mCurrentMemberMeta = prevMeta;
720  }
721 
726  template<typename T>
728  {
730  }
731 
732 
737  template<typename T>
739  {
740  try {
741  this->invokeMember(member,meta);
742  } catch (XMemberNotFound& ex) {
743  throw XMemberNotFound_NoDefault(ex);
744  // transform exception to avoid catching it
745  // in upper levels, where it might be shadowed
746  // if a default value is given there (see #685)
747  } catch(Exception& ex) {
748  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
749  throw;
750 
751  MIRA_RETHROW(ex, "while " <<
752  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
753  " '" << meta.getName() << "'");
754  }
755  }
756 
762  template<typename T, typename U>
764  const U& defaultValue)
765  {
766  try {
767  this->invokeMember(member,meta);
768  } catch (XMemberNotFound_NoDefault&) {
769  throw; // must not handle this
770  } catch (XMemberNotFound&) {
771  if(!Derived::isReadOnly::value) {
772  MIRA_LOG(NOTICE) << "No value given for '" << meta.name << "', "
773  "using the default value instead.";
774 
775  // #############################################################
776  // If you get a compiler error here, your default value does not
777  // match to your member type and cannot be casted. Make sure
778  // that the data type of your default value can be casted to
779  // the data type of your member!
780  // #############################################################
781  try {
782  member=defaultValue;
783  } catch(Exception& ex) {
784  MIRA_RETHROW(ex, "while default-initializing '" << meta.getName() << "'");
785  }
786  }
787  } catch(Exception& ex) {
788  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
789  throw;
790 
791  MIRA_RETHROW(ex, "while " <<
792  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
793  " '" << meta.getName() << "'");
794  }
795  }
796 
803  template<typename T>
805  const serialization::IgnoreMissing& defaultValue)
806  {
807  try {
808  this->invokeMember(member,meta);
809  } catch (XMemberNotFound_NoDefault&) {
810  throw; // must not handle this
811  } catch (XMemberNotFound&) {
812  // IGNORE
813  } catch(Exception& ex) {
814  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
815  throw;
816 
817  MIRA_RETHROW(ex, "while " <<
818  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
819  " '" << meta.getName() << "'");
820  }
821  }
822 
824 
825 private:
826 
827  const ReflectMemberMeta* mCurrentMemberMeta;
828  std::string mCurrentMemberFullID;
829 
830 };
831 
833 
852 template <typename Derived>
854 {
855 public:
856 
857  // implement our supported visiting methods of the ReflectorInterface
858  // note: the documentation of the following methods is inherited from
859  // ReflectorInterface by Doxygen
860 
861  template<typename T>
862  void member(const char* name, T& member, const char* comment,
864  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
865  this->This()->pushObjectTrackingStore();
866  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
867  this->This()->popObjectTrackingStore();
868  } else
869  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
870  }
871 
872  template<typename T>
873  void member(const char* name, const std::string& id, T& member,
874  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
875  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
876  this->This()->pushObjectTrackingStore();
877  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
878  comment) );
879  this->This()->popObjectTrackingStore();
880  } else
881  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
882  comment) );
883  }
884 
885  template<typename T>
886  void member(const char* name, const T& member, Setter<T> setter,
887  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
888  auto a = makeAccessor(member, setter);
889  this->This()->pushObjectTrackingStore();
890  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
891  this->This()->popObjectTrackingStore();
892  }
893 
894  template<typename T>
895  void member(const char* name, Getter<T> getter, Setter<T> setter,
896  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
897  auto a = makeAccessor(getter, setter);
898  this->This()->pushObjectTrackingStore();
899  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
900  this->This()->popObjectTrackingStore();
901  }
902 
903  // avoid member("MyMember", member, "my member", {}) (most probably meant to
904  // set default-initialized object as deserialization default) unambiguously matching
905  // Reflector::member(name, member, comment, flags). see #910
906  template<typename T>
907  void member(const char* name, T& member, const char* comment,
908  const T& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
909  this->template member<T, T>(name, member, comment, defaultValue, flags);
910  }
911 
912  template<typename T, typename U>
913  void member(const char* name, T& member, const char* comment,
914  const U& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
915  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
916  this->This()->pushObjectTrackingStore();
917  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
918  defaultValue);
919  this->This()->popObjectTrackingStore();
920  } else
921  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
922  defaultValue);
923  }
924 
925  // see above. see #910
926  template<typename T>
927  void member(const char* name, const T& member, Setter<T> setter,
928  const char* comment, const T& defaultValue,
930  this->template member<T, T>(name, member, setter, comment, defaultValue, flags);
931  }
932 
933  template<typename T, typename U>
934  void member(const char* name, const T& member, Setter<T> setter,
935  const char* comment, const U& defaultValue,
937  auto a = makeAccessor(member, setter);
938  this->This()->pushObjectTrackingStore();
939  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
940  defaultValue );
941  this->This()->popObjectTrackingStore();
942  }
943 
944  // see above. see #910
945  template<typename T>
946  void member(const char* name, Getter<T> getter, Setter<T> setter,
947  const char* comment, const T& defaultValue,
949  this->template member<T, T>(name, getter, setter, comment, defaultValue, flags);
950  }
951 
952  template<typename T, typename U>
953  void member(const char* name, Getter<T> getter, Setter<T> setter,
954  const char* comment, const U& defaultValue,
956  auto a = makeAccessor(getter, setter);
957  this->This()->pushObjectTrackingStore();
958  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
959  defaultValue );
960  this->This()->popObjectTrackingStore();
961  }
962 
963  template<typename T>
964  void property(const char* name, T& member, const char* comment,
965  PropertyHint&& hint = PropertyHint(),
967  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
968  this->This()->pushObjectTrackingStore();
969  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
970  this->This()->popObjectTrackingStore();
971  } else
972  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
973  }
974 
975  template<typename T>
976  void property(const char* name, const std::string& id, T& member,
977  const char* comment, PropertyHint&& hint = PropertyHint(),
979  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
980  this->This()->pushObjectTrackingStore();
981  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
982  this->This()->popObjectTrackingStore();
983  } else
984  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
985  }
986 
987  template<typename T>
988  void property(const char* name, const T& member, Setter<T> setter,
989  const char* comment, PropertyHint&& hint = PropertyHint(),
991  auto a = makeAccessor(member, setter);
992  this->This()->pushObjectTrackingStore();
993  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
994  this->This()->popObjectTrackingStore();
995  }
996 
997  template<typename T>
998  void property(const char* name, Getter<T> getter, Setter<T> setter,
999  const char* comment, PropertyHint&& hint = PropertyHint(),
1001  auto a = makeAccessor(getter, setter);
1002  this->This()->pushObjectTrackingStore();
1003  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
1004  this->This()->popObjectTrackingStore();
1005  }
1006 
1007  // see above. see #910
1008  template<typename T>
1009  void property(const char* name, T& member, const char* comment,
1010  const T& defaultValue, PropertyHint&& hint = PropertyHint(),
1012  this->template property<T, T>(name, member, comment, defaultValue, std::move(hint), flags);
1013  }
1014 
1015  template<typename T, typename U>
1016  void property(const char* name, T& member, const char* comment,
1017  const U& defaultValue, PropertyHint&& hint = PropertyHint(),
1019  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1020  this->This()->pushObjectTrackingStore();
1021  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1022  defaultValue);
1023  this->This()->popObjectTrackingStore();
1024  } else
1025  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1026  defaultValue);
1027  }
1028 
1029  // see above. see #910
1030  template<typename T>
1031  void property(const char* name, const T& member, Setter<T> setter,
1032  const char* comment, const T& defaultValue,
1033  PropertyHint&& hint = PropertyHint(),
1035  this->template property<T, T>(name, member, setter, comment, defaultValue, std::move(hint), flags);
1036  }
1037 
1038  template<typename T, typename U>
1039  void property(const char* name, const T& member, Setter<T> setter,
1040  const char* comment, const U& defaultValue,
1041  PropertyHint&& hint = PropertyHint(),
1043  auto a = makeAccessor(member, setter);
1044  this->This()->pushObjectTrackingStore();
1045  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1046  defaultValue );
1047  this->This()->popObjectTrackingStore();
1048  }
1049 
1050  // see above. see #910
1051  template<typename T>
1052  void property(const char* name, Getter<T> getter, Setter<T> setter,
1053  const char* comment, const T& defaultValue,
1054  PropertyHint&& hint = PropertyHint(),
1056  this->template property<T, T>(name, getter, setter, comment, defaultValue, std::move(hint), flags);
1057  }
1058 
1059  template<typename T, typename U>
1060  void property(const char* name, Getter<T> getter, Setter<T> setter,
1061  const char* comment, const U& defaultValue,
1062  PropertyHint&& hint = PropertyHint(),
1064  auto a = makeAccessor(getter, setter);
1065  this->This()->pushObjectTrackingStore();
1066  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1067  defaultValue );
1068  this->This()->popObjectTrackingStore();
1069  }
1070 
1077  template<typename T>
1079  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1080  this->This()->pushObjectTrackingStore();
1081  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1082  this->This()->popObjectTrackingStore();
1083  } else
1084  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1085  }
1086 
1093  template<typename T>
1096  auto a = makeAccessor(member, setter);
1097  this->This()->pushObjectTrackingStore();
1098  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1099  this->This()->popObjectTrackingStore();
1100  }
1101 
1108  template<typename T>
1111  auto a = makeAccessor(getter, setter);
1112  this->This()->pushObjectTrackingStore();
1113  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1114  this->This()->popObjectTrackingStore();
1115  }
1116 
1117 };
1118 
1120 
1121 }
1122 
1123 #endif
TypeId typeId()
Generates unique IDs for different types.
Definition: TypeId.h:94
This object can use object tracking internally, but the object tracking system&#39;s state remains unchan...
Definition: ReflectControlFlags.h:82
void reflectPointerAbstract(T *&member)
Type C3: for members that are pointers to abstract classes not derived from mira::Object.
Definition: RecursiveMemberReflector.h:603
Type trait that indicates whether pointer tracking can be enabled for this type.
Definition: IsObjectTrackable.h:68
void object(T &member)
Is called for each complex object.
Definition: RecursiveMemberReflector.h:301
std::string getName() const
Definition: ReflectMemberMeta.h:82
Provides safe casts for casting from a pointer to void* and vice versa while taking care of polymorph...
void property(const char *name, T &member, const char *comment, const U &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1016
void property(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:998
void member(const char *name, const T &member, Setter< T > setter, const char *comment, const U &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:934
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
void reflectPointerPolymorphic(T *&member)
Type C2: for members that are pointers to polymorphic classes derived from mira::Object.
Definition: RecursiveMemberReflector.h:584
void member(const char *name, const T &member, Setter< T > setter, const char *comment, const T &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:927
Abstract base class for most Reflectors.
const std::string & getCurrentMemberFullID() const
Returns the full human readable object id / name of the current member being reflected.
Definition: RecursiveMemberReflector.h:470
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:862
void property(const char *name, T &member, const char *comment, const T &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1009
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
void trackObject(T &member)
Definition: RecursiveMemberReflector.h:317
Class object which supports some kind of class reflection.
Definition: Class.h:97
#define MIRA_RETHROW(ex, msg)
Macro for rethrowing an exception with file and line information and for adding additional informatio...
Definition: Exception.h:148
Contains toString and fromString functions for converting data types to strings and the other way rou...
#define MIRA_DEFINE_SERIALIZABLE_EXCEPTION(Ex, Base)
Macro for easily defining a new serializable exception class.
Definition: Exceptions.h:66
Setter< T > setter(void(*f)(const T &))
Creates a Setter for global or static class methods taking the argument by const reference.
Definition: GetterSetter.h:443
Holds a boost::function object to a special setter function that must meet the signature "void method...
Definition: GetterSetter.h:395
Stores meta information for each member.
Definition: ReflectMemberMeta.h:64
Type trait that indicates whether a type can be serialized as an atomic value.
Definition: IsAtomicSerializable.h:83
const char * name
The name (as specified in the XML file).
Definition: ReflectMemberMeta.h:67
void property(const char *name, T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:964
Provided for convenience.
Definition: Singleton.h:564
void chooseReflect(T &member)
Detect the members type (A1,A2,A3,B1,B2,C) and choose the appropriate function.
Definition: RecursiveMemberReflector.h:612
Provides type trait that indicates whether a type should be serialized "transparently".
Provides type trait that indicates whether pointer/object tracking should be enabled for a certain ty...
Contains internal accessor class that abstracts from the underlying getter and setter classes or dire...
void invokeMemberWithDefault(T &member, const ReflectMemberMeta &meta, const U &defaultValue)
Delegates to invokeMember() and handles any occurring XMemberNotFound exception by setting the member...
Definition: RecursiveMemberReflector.h:763
void pointerAbstract(T *&pointer, int typeId)
Is called if a reflected pointer is a pointer to an abstract class.
Definition: RecursiveMemberReflector.h:406
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:82
Marker for indicating parameters that should be ignored if they are missing in the config file...
void property(const char *name, const T &member, Setter< T > setter, const char *comment, const U &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1039
A property hint gives optional instructions to the property editor, i.e.
Definition: PropertyHint.h:82
Derived * This()
"Curiously recurring template pattern" (CRTP).
Definition: AbstractReflector.h:246
Wrapper class for reflecting arrays.
XMemberNotFound_NoDefault() MIRA_NOEXCEPT_OR_NOTHROW
Definition: RecursiveMemberReflector.h:128
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:459
void property(const char *name, const std::string &id, T &member, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:976
Abstract base class for most Reflectors.
Definition: AbstractReflector.h:160
static bool usesHumanReadableIDs()
Returns true, if the concrete derived Reflector supports human readable IDs.
Definition: ReflectorInterface.h:801
Marker for indicating parameters that should be ignored if they are missing in the config file...
Definition: IgnoreMissing.h:73
Can be thrown by subclasses of RecursiveMemberReflectorBase to indicate that they did not find a cert...
Definition: RecursiveMemberReflector.h:123
$Header file containing base classes to enable class creation using a class factory$ ...
Implementation of the InstantiationPolicy that is used by the Singleton template. ...
Definition: Singleton.h:339
void pointerPolymorphic(T *&pointer, int typeId)
Is called if a reflected pointer is a polymorphic pointer to an object that is derived from mira::Obj...
Definition: RecursiveMemberReflector.h:367
void delegate(Getter< T > getter, Setter< T > setter, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Delegates the serialization directly to the specified member, without creating a separate compound fo...
Definition: RecursiveMemberReflector.h:1109
Struct to take meta information for each reflected member.
static bool isReflectedAsPointer()
For internal use only: Returns true, if the type T is ever reflected as pointer within the current tr...
Definition: RecursiveMemberReflector.h:484
SetReflectedAsPointer()
Definition: RecursiveMemberReflector.h:103
A singleton template class that can be freely configured using policies that control the instantiatio...
Definition: Singleton.h:531
void pointerNormal(T *&pointer, int typeId)
Is called if a reflected pointer is a "normal" pointer.
Definition: RecursiveMemberReflector.h:352
No flags.
Definition: ReflectControlFlags.h:65
A singleton class that can be freely configured using policies that control the creation, instantiation, lifetime and thread-safety.
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
void invokeTrackObject(T &member)
tracks the given object (if pointer tracking is enabled for type T)
Definition: RecursiveMemberReflector.h:491
void reflectPointer(T &member)
Type C: for members that are pointers.
Definition: RecursiveMemberReflector.h:568
Core class of the logging library.
void delegate(T &member, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Delegates the serialization directly to the specified member, without creating a separate compound fo...
Definition: RecursiveMemberReflector.h:1078
void reflectUnknown(T &member)
Definition: RecursiveMemberReflector.h:503
void invokePointerObject(T &member)
Is called to reflect objects of pointers.
Definition: RecursiveMemberReflector.h:727
bool value
Definition: RecursiveMemberReflector.h:98
void property(const char *name, const T &member, Setter< T > setter, const char *comment, const T &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1031
Getter< T > getter(T(*f)())
Creates a Getter for global or static class methods returning the result by value.
Definition: GetterSetter.h:136
The RecursiveMemberReflectorBase is a base class for all Reflectors that are used to visit the reflec...
Definition: RecursiveMemberReflector.h:233
static void unregisterClass()
Unregisters the class.
Definition: RecursiveMemberReflector.h:448
Provides type trait that indicates whether a type is a collection.
void property(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, const U &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1060
void property(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, const T &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1052
void invokeMemberWithoutDefault(T &member, const ReflectMemberMeta &meta)
Delegates to invokeMember() and rethrows any occurring XMemberNotFound exception as XIO exception...
Definition: RecursiveMemberReflector.h:738
void member(const char *name, T &member, const char *comment, const U &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:913
virtual std::string const & getIdentifier() const
Return identifier for the class.
void member(const char *name, const std::string &id, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:873
RecursiveMemberReflectorBase()
The constructor.
Definition: RecursiveMemberReflector.h:239
#define MIRA_NOEXCEPT_OR_NOTHROW
Definition: NoExcept.h:99
#define MIRA_OBJECT(classIdentifier)
Use this MACRO if you like the factory to automatically extract the class name from the given identif...
Definition: FactoryMacros.h:179
XMemberNotFound_NoDefault(XMemberNotFound &ex) MIRA_NOEXCEPT_OR_NOTHROW
Definition: RecursiveMemberReflector.h:131
Implementation of the CreationPolicy that is used by the Singleton template.
Definition: Singleton.h:190
Base class for exceptions.
Definition: Exception.h:199
void member(const char *name, const T &member, Setter< T > setter, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:886
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Specifies a class member for reflection/serialization.
Definition: ReflectorInterface.h:375
Holds a boost::function object to a special getter function that must meet the signature "T method()"...
Definition: GetterSetter.h:87
For internal use only: Holds value=true, if the type T is ever reflected as pointer with Reflector wi...
Definition: RecursiveMemberReflector.h:96
void member(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, const T &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:946
void invokeMember(T &member, const ReflectMemberMeta &meta)
Is called to invoke this Reflector on the member with the specified meta information.
Definition: RecursiveMemberReflector.h:653
Provides type trait that indicates whether a type can be serialized as atomic value.
void property(const char *name, const T &member, Setter< T > setter, const char *comment, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:988
void pointer(T *&pointer)
Is called if the member is a pointer.
Definition: RecursiveMemberReflector.h:325
void delegate(const T &member, Setter< T > setter, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Delegates the serialization directly to the specified member, without creating a separate compound fo...
Definition: RecursiveMemberReflector.h:1094
void reflectCollection(T &member)
Type B?c: for collection types.
Definition: RecursiveMemberReflector.h:555
static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME
Use this when a reflector needs to choose a name for serializing an object.
Definition: RecursiveMemberReflector.h:249
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
The actual invokeMember implementation that is called from invokeMember().
Definition: RecursiveMemberReflector.h:665
void enumeration(T &member)
Is called by the if the member is an enumeration.
Definition: RecursiveMemberReflector.h:281
ReflectCtrlFlags
Control Flags that can modify the behavior of certain reflectors.
Definition: ReflectControlFlags.h:63
void reflectEnumeration(T &member)
Type A2: for enums.
Definition: RecursiveMemberReflector.h:518
void collection(T &member)
Is called for each complex object or array, where the IsCollection<T> trait is true_type.
Definition: RecursiveMemberReflector.h:311
void reflectComplex(T &member)
Type B1/B2: for complex types.
Definition: RecursiveMemberReflector.h:540
Type trait that indicates whether a type is a collection.
Definition: IsCollection.h:63
void member(const char *name, T &member, const char *comment, const T &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:907
void member(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:895
static void registerClass()
Registers a new polymorphic class at the PolymorphPointerReflector.
Definition: RecursiveMemberReflector.h:429
void member(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, const U &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:953
Definition: IsTransparentSerializable.h:84
Accessor< Getter, Setter > makeAccessor(const Getter &getter, const Setter &setter)
Helper method that creates an accessor from a different combination of either direct access to a vari...
Definition: Accessor.h:300
void reflectPointerNormal(T *&member)
Type C1: for members that are pointers to normal classes.
Definition: RecursiveMemberReflector.h:577
The RecursiveMemberReflector extents the RecursiveMemberReflectorBase class and implements the member...
Definition: RecursiveMemberReflector.h:853
void * void_upcast(T *pointer)
Safe cast for casting from a pointer upwards to void* while taking care of polymorphism and multiple ...
Definition: VoidCast.h:108
const char * id
The id (used for containers where the name is identical, in all other cases the id usually is equal t...
Definition: ReflectMemberMeta.h:73
Definition: RecursiveMemberReflector.h:102
For internal use by RecursiveMemberReflector.h!
void atomic(T &member)
Is called if the member is an atomic type (int, float, etc).
Definition: RecursiveMemberReflector.h:268
void reflectArray(T &member)
Type A3: for arrays.
Definition: RecursiveMemberReflector.h:526
void reflectAtomic(T &member)
Type A1: for atomic members (float,int,etc.)
Definition: RecursiveMemberReflector.h:510
Definition: LoggingCore.h:77
void invokeMemberWithDefault(T &member, const ReflectMemberMeta &meta, const serialization::IgnoreMissing &defaultValue)
Delegates to invokeMember() and handles any occurring XMemberNotFound exception by ignoring the excep...
Definition: RecursiveMemberReflector.h:804
virtual int getTypeId() const =0
Return unique id for the class.