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 
85 {
86 public:
87  [[nodiscard]] bool query() const
88  {
89  return isOn;
90  }
91 
92  void set()
93  {
94  isOn = true;
95  }
96 
97 private:
98  bool isOn = false;
99 };
100 
112 template<typename T, typename Reflector>
114 {
115  static OneWaySwitch value{};
116  return value;
117 }
118 
119 template<typename T, typename Reflector>
121 {
123  {
124  reflectedAsPointer<T, Reflector>().set();
125  }
126 };
127 
129 
130 // Helper to analyze if typename DelegateTo is defined in DelegatingType
131 template<typename DelegatingType, typename = void>
132 struct HasDelegateTo : std::false_type {
133 };
134 
135 template<typename DelegatingType>
136 struct HasDelegateTo<DelegatingType, std::void_t<typename DelegatingType::DelegateTo>> : std::true_type {};
137 
157 template<typename DelegatingType, typename SerializerTag>
159 {
160  MIRA_DEPRECATED("Please define (public!) type DelegateTo in specialization of IsTransparentSerializable<DelegatingType, SerializerTag> "
161  "to enable properly detecting the possibility of child members/properties",
162  static constexpr void warn(){}
163  )
164 };
165 
172 template<typename T, typename SerializerTag = void>
173 constexpr bool hasRecursiveReflect()
174 {
175  if constexpr (IsAtomicSerializable<T>::value)
176  return false;
177  if constexpr (std::is_enum_v<T>)
178  return false;
179 
180  using TransparentTrait = IsTransparentSerializable<T, SerializerTag>;
181 
182  if constexpr (TransparentTrait::value) {
184  return hasRecursiveReflect<typename TransparentTrait::DelegateTo, SerializerTag>();
185  } else
187  }
188 
189  return true;
190 };
191 
193 
194 } // namespace
195 
200 MIRA_DEFINE_SERIALIZABLE_EXCEPTION(XMemberNotFound, XIO)
201 
202 
207 class XMemberNotFound_NoDefault : public XMemberNotFound
208 {
210 protected:
211  friend class ClassFactoryDefaultConstClassBuilder;
213 
214 public:
216  XMemberNotFound(ex) {}
217 
218  void raise(bool recursive = false) override
219  {
220  // The exception object is copy-initialized from *this.
221  throw *this;
222  }
223 };
224 
226 
316 template <typename Derived>
318 {
320 public:
321 
324  mCurrentMemberMeta(nullptr) {}
325 
326 protected:
327 
333  static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME = "@value";
334 
335 public:
336 
341 
351  template<typename T>
352  void atomic(T& member) {}
353 
364  template<typename T>
365  void enumeration(T& member) {
366  if constexpr(Derived::isReadOnly::value) {
367  auto val = static_cast<int32>(member);
368  this->This()->atomic(val);
369  } else {
370  int32 val;
371  this->This()->atomic(val);
372  member = static_cast<T>(val);
373  }
374  }
375 
384  template<typename T>
385  void object(T& member) {
386  this->This()->invoke(member); // invoke us recursively on the object
387  }
388 
394  template<typename T>
395  void collection(T& member) {
396  this->This()->object(member); // default impl calls object()
397  }
398 
399 
400  template<typename T>
401  void trackObject(T& member) {}
402 
408  template<typename T>
409  void pointer(T*& pointer)
410  {
411  // this will instantiate the SetReflectedAsPointer during startup
412  // which will set reflectedAsPointer<T,Derived>::value to true,
413  // and mark that T was reflected as pointer by Derived at least once.
415  singleton::CreateStatic>::instance();
416 
417  if constexpr (std::is_base_of_v<mira::Object, T>) {
419  }
420  else if constexpr (std::is_abstract_v<T>) {
422  }
423  else {
425  }
426  }
427 
435  template<typename T>
436  void pointerNormal(T*& pointer, int typeId)
437  {
438  if (pointer != nullptr) // delegate serialization of the actual object recursively
439  this->This()->invokePointerObject(*pointer);
440  }
441 
450  template<typename T>
452  {
453  if (pointer != nullptr) { // delegate serialization of the actual object recursively
454 
455  try {
456  // obtain a special polymorph pointer serializer for the derived type
457  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
458 
459  typename OurRegistrar::ReflectorRef r =
460  OurRegistrar::instance().getPolymorphicPointerReflector(typeId);
461 
462  // deserialize the content recursively
463  r.invoke(*this->This(), serialization::void_upcast(pointer));
464  }
465  catch (XPolymorphicPointerReflectorNotRegistered&) {
466  const ReflectMemberMeta& meta = getCurrentMemberMeta();
467  const Class& c = pointer->getClass();
468  MIRA_THROW(XIO,
469  "Cannot reflect the polymorphic member pointer '"
470  << meta.name << "'. The class '" << c.getIdentifier()
471  << "' was not registered with this serializer '" << typeName<Derived>()
472  << "'"
473 #ifndef MIRA_REGISTER_LEGACY_SERIALIZERS
474  << " (Registration with legacy serializers must be explicitly enabled"
475  " by activating the option REGISTER_LEGACY_SERIALIZERS"
476  " [GlobalConfig, requires recompilation])";
477 #endif
478  );
479  }
480  }
481  }
482 
489  template<typename T>
491  {
492  if (pointer != nullptr) // delegate serialization of the actual object recursively
493  this->This()->invokePointerObject(*pointer);
494  }
495 
497 
498 public:
499 
512  template<typename T>
513  static void registerClass()
514  {
515  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
516 
517  if(!OurRegistrar::isDestroyed())
518  OurRegistrar::instance().template registerClass<T>();
519  }
520 
531  template<typename T>
532  static void unregisterClass()
533  {
534  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
535  if(!OurRegistrar::isDestroyed())
536  OurRegistrar::instance().template unregisterClass<T>();
537  }
538 public:
539 
543  [[nodiscard]] const ReflectMemberMeta& getCurrentMemberMeta() const
544  {
545  assert(mCurrentMemberMeta!=nullptr);
546  return *mCurrentMemberMeta;
547  }
548 
554  [[nodiscard]] const std::string& getCurrentMemberFullID() const
555  {
556  assert(this->usesHumanReadableIDs());
557  return mCurrentMemberFullID;
558  }
559 
560 public:
561 
567  template<typename T>
568  static bool isReflectedAsPointer()
569  {
570  return serialization::reflectedAsPointer<T, Derived>().query();
571  }
572 
573 protected:
575  template<typename T>
577  {
578  if constexpr (IsObjectTrackable<T>::value)
579  this->This()->trackObject(member);
580  }
581 
582  // The following structs implement different invoke methods for each of
583  // the member types (A1-3, B1-2, C). The member types are detected in
584  // the invoke method above which delegates to the invoke method
585  // of the correct struct below.
586 
587  template<typename T>
589  {
590  static_assert(sizeof(T) == 0, "Trying to reflect unknown type.");
591  }
592 
594  template<typename T>
596  {
597  this->This()->invokeTrackObject(member);
598  this->This()->atomic(member);
599  }
600 
602  template<typename T>
604  {
605  this->This()->invokeTrackObject(member);
606  this->This()->enumeration(member);
607  }
608 
610  template<typename T>
612  {
613  this->This()->invokeTrackObject(member);
614  std::size_t size = sizeof(member)
615  / (static_cast<const char*>(static_cast<const void*>(&member[1]))
616  - static_cast<const char*>(static_cast<const void*>(&member[0])));
617 
618  typedef typename std::remove_extent<T>::type ItemType;
619  serialization::Array<ItemType> array(member, size);
620  reflectCollection(array);
621  }
622 
624  template<typename T>
626  {
627  this->This()->invokeTrackObject(member);
628  typedef typename std::remove_cv<T>::type Type;
629  static_assert(!IsCollection<Type>::value,
630  "Trying to call reflectComplex<T>() with IsCollection<T> == true "
631  "- something is wrong.");
633  this->This()->invoke(member);
634  else
635  this->This()->object(member);
636  }
637 
639  template<typename T>
641  {
642  this->This()->invokeTrackObject(member);
643  typedef typename std::remove_cv<T>::type Type;
645  static_assert(!isTransparent::value,
646  "Trying to call reflectCollection<T>() with IsTransparentSerializable<T> == "
647  "true - something is wrong.");
648  this->This()->collection(member);
649  }
650 
652  template<typename T>
654  {
655  this->This()->pointer(member);
656  }
657 
658  // The following ReflectPointerXXX structs are used by our pointer() method
659 
661  template<typename T>
663  {
664  this->This()->pointerNormal(member, typeId<T>());
665  }
666 
668  template<typename T>
670  {
671  int typeId = -1;
672 
673  if (member != nullptr) {
674  // we have an object, so we can obtain its class information
675  const Class& c = member->getClass();
676  typeId = c.getTypeId();
677  }
678 
679  // call pointerPolymorphic()
680  this->This()->pointerPolymorphic(member, typeId);
681  }
682 
687  template<typename T>
689  {
690  this->This()->pointerAbstract(member, typeId<T>());
691  }
692 
696  template<typename T>
698  {
699  using Type = typename std::remove_cv<T>::type;
700  if constexpr (std::is_pointer_v<Type>) {
702  } // T is a pointer (Type C)
703  else if constexpr (IsAtomicSerializable<Type>::value) {
705  } // atomic (Type A1)
706  else if constexpr (std::is_class_v<Type>) {
707  if constexpr (IsCollection<Type>::value) {
709  } // T is a collection (Type B?c)
710  else {
712  } // T is a complex class (Type B1/B2)
713  }
714  else if constexpr (std::is_enum_v<Type>) {
716  } // enum (Type A2)
717  else if constexpr (std::is_array_v<Type>) {
719  } // T is no pointer, no class --> must be atomic or enum
720  else {
722  }
723  }
724 
725 public:
726 
737  template<typename T>
738  void invokeMember(T& member, const ReflectMemberMeta& meta)
739  {
740  this->This()->invokeMemberOverwrite(member, meta);
741  }
742 
749  template<typename T>
751  {
752  // store previous meta (it is restored at the end of this method
753  // and therefore implements a stack, where mCurrentMemberMeta is
754  // the top element in the stack)
755  const ReflectMemberMeta* prevMeta = mCurrentMemberMeta;
756 
757  // do the same to create a stack of the full human readable object
758  // id (however, only do it, if our final reflector supports human
759  // readable id's, otherwise skip this step since it hurts the
760  // performance
761  std::string prevFullID;
762  if(this->usesHumanReadableIDs()) {
763  prevFullID = mCurrentMemberFullID;
764 
765  // "push" new full id
766  if(mCurrentMemberFullID.empty()) {
767  if(meta.id==nullptr)
768  MIRA_THROW(XLogical, "Top-level member cannot be 'inline'. "
769  "It must have an ID != NULL!");
770  mCurrentMemberFullID=meta.id;
771  } else if(meta.id!=nullptr)
772  mCurrentMemberFullID = mCurrentMemberFullID + "." + meta.id;
773  }
774 
775  // "push" current meta (but only if member is not transparent, which is
776  // indicated by an id of NULL)
777  if(meta.id != nullptr)
778  mCurrentMemberMeta = &meta;
779 
780  // Choose the type of the member and select the
781  // correct ReflectXYZ struct for that type at compile type.
782  // Then call the invoke method of that struct.
783  // (The different structures and their invoke methods are defined
784  // above)
785  try
786  {
788  }
789  catch(...)
790  {
791  // "pop" our id
792  if(this->usesHumanReadableIDs())
793  mCurrentMemberFullID=prevFullID;
794  // "pop" our meta data stack.
795  mCurrentMemberMeta = prevMeta;
796  // and throw
797  throw;
798  }
799 
800  // "pop" our id
801  if(this->usesHumanReadableIDs())
802  mCurrentMemberFullID=prevFullID;
803  // "pop" our meta data stack.
804  mCurrentMemberMeta = prevMeta;
805  }
806 
811  template<typename T>
813  {
815  }
816 
817 
822  template<typename T>
824  {
825  try {
826  this->invokeMember(member,meta);
827  } catch (XMemberNotFound& ex) {
828  throw XMemberNotFound_NoDefault(ex);
829  // transform exception to avoid catching it
830  // in upper levels, where it might be shadowed
831  // if a default value is given there (see #685)
832  } catch(Exception& ex) {
833  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
834  throw;
835 
836  MIRA_RETHROW(ex, "while " <<
837  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
838  " '" << meta.getName() << "'");
839  }
840  }
841 
847  template<typename T, typename U>
849  const U& defaultValue)
850  {
851  try {
852  this->invokeMember(member,meta);
853  } catch (XMemberNotFound_NoDefault&) {
854  throw; // must not handle this
855  } catch (XMemberNotFound&) {
856  if constexpr(!Derived::isReadOnly::value) {
857  MIRA_LOG(NOTICE) << "No value given for '" << meta.name << "', "
858  "using the default value instead.";
859 
860  // #############################################################
861  // If you get a compiler error here, your default value does not
862  // match to your member type and cannot be casted. Make sure
863  // that the data type of your default value can be casted to
864  // the data type of your member!
865  // #############################################################
866  try {
867  member=defaultValue;
868  } catch(Exception& ex) {
869  MIRA_RETHROW(ex, "while default-initializing '" << meta.getName() << "'");
870  }
871  }
872  } catch(Exception& ex) {
873  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
874  throw;
875 
876  MIRA_RETHROW(ex, "while " <<
877  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
878  " '" << meta.getName() << "'");
879  }
880  }
881 
888  template<typename T>
890  const serialization::IgnoreMissing& defaultValue)
891  {
892  try {
893  this->invokeMember(member,meta);
894  } catch (XMemberNotFound_NoDefault&) {
895  throw; // must not handle this
896  } catch (XMemberNotFound&) {
897  // IGNORE
898  } catch(Exception& ex) {
899  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
900  throw;
901 
902  MIRA_RETHROW(ex, "while " <<
903  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
904  " '" << meta.getName() << "'");
905  }
906  }
907 
909 
910 private:
911 
912  const ReflectMemberMeta* mCurrentMemberMeta;
913  std::string mCurrentMemberFullID;
914 
915 };
916 
918 
937 template <typename Derived>
939 {
940 public:
941 
942  // implement our supported visiting methods of the ReflectorInterface
943  // note: the documentation of the following methods is inherited from
944  // ReflectorInterface by Doxygen
945 
946  template<typename T>
947  void member(const char* name, T& member, const char* comment,
949  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
950  this->This()->pushObjectTrackingStore();
951  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
952  this->This()->popObjectTrackingStore();
953  } else
954  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
955  }
956 
957  template<typename T>
958  void member(const char* name, const std::string& id, T& member,
959  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
960  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
961  this->This()->pushObjectTrackingStore();
962  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
963  comment) );
964  this->This()->popObjectTrackingStore();
965  } else
966  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
967  comment) );
968  }
969 
970  template<typename T>
971  void member(const char* name, const T& member, Setter<T> setter,
972  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
973  auto a = makeAccessor(member, setter);
974  this->This()->pushObjectTrackingStore();
975  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
976  this->This()->popObjectTrackingStore();
977  }
978 
979  template<typename T>
980  void member(const char* name, Getter<T> getter, Setter<T> setter,
981  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
982  auto a = makeAccessor(getter, setter);
983  this->This()->pushObjectTrackingStore();
984  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
985  this->This()->popObjectTrackingStore();
986  }
987 
988  // avoid member("MyMember", member, "my member", {}) (most probably meant to
989  // set default-initialized object as deserialization default) unambiguously matching
990  // Reflector::member(name, member, comment, flags). see #910
991  template<typename T>
992  void member(const char* name, T& member, const char* comment,
993  const T& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
994  this->template member<T, T>(name, member, comment, defaultValue, flags);
995  }
996 
997  template<typename T, typename U>
998  void member(const char* name, T& member, const char* comment,
999  const U& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
1000  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1001  this->This()->pushObjectTrackingStore();
1002  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1003  defaultValue);
1004  this->This()->popObjectTrackingStore();
1005  } else
1006  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1007  defaultValue);
1008  }
1009 
1010  // see above. see #910
1011  template<typename T>
1012  void member(const char* name, const T& member, Setter<T> setter,
1013  const char* comment, const T& defaultValue,
1015  this->template member<T, T>(name, member, setter, comment, defaultValue, flags);
1016  }
1017 
1018  template<typename T, typename U>
1019  void member(const char* name, const T& member, Setter<T> setter,
1020  const char* comment, const U& defaultValue,
1022  auto a = makeAccessor(member, setter);
1023  this->This()->pushObjectTrackingStore();
1024  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1025  defaultValue );
1026  this->This()->popObjectTrackingStore();
1027  }
1028 
1029  // see above. see #910
1030  template<typename T>
1031  void member(const char* name, Getter<T> getter, Setter<T> setter,
1032  const char* comment, const T& defaultValue,
1034  this->template member<T, T>(name, getter, setter, comment, defaultValue, flags);
1035  }
1036 
1037  template<typename T, typename U>
1038  void member(const char* name, Getter<T> getter, Setter<T> setter,
1039  const char* comment, const U& defaultValue,
1041  auto a = makeAccessor(getter, setter);
1042  this->This()->pushObjectTrackingStore();
1043  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1044  defaultValue );
1045  this->This()->popObjectTrackingStore();
1046  }
1047 
1048  template<typename T>
1049  void property(const char* name, T& member, const char* comment,
1050  PropertyHint&& hint = PropertyHint(),
1052  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1053  this->This()->pushObjectTrackingStore();
1054  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
1055  this->This()->popObjectTrackingStore();
1056  } else
1057  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
1058  }
1059 
1060  template<typename T>
1061  void property(const char* name, const std::string& id, T& member,
1062  const char* comment, PropertyHint&& hint = PropertyHint(),
1064  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1065  this->This()->pushObjectTrackingStore();
1066  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
1067  this->This()->popObjectTrackingStore();
1068  } else
1069  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
1070  }
1071 
1072  template<typename T>
1073  void property(const char* name, const T& member, Setter<T> setter,
1074  const char* comment, PropertyHint&& hint = PropertyHint(),
1076  auto a = makeAccessor(member, setter);
1077  this->This()->pushObjectTrackingStore();
1078  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
1079  this->This()->popObjectTrackingStore();
1080  }
1081 
1082  template<typename T>
1083  void property(const char* name, Getter<T> getter, Setter<T> setter,
1084  const char* comment, PropertyHint&& hint = PropertyHint(),
1086  auto a = makeAccessor(getter, setter);
1087  this->This()->pushObjectTrackingStore();
1088  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
1089  this->This()->popObjectTrackingStore();
1090  }
1091 
1092  // see above. see #910
1093  template<typename T>
1094  void property(const char* name, T& member, const char* comment,
1095  const T& defaultValue, PropertyHint&& hint = PropertyHint(),
1097  this->template property<T, T>(name, member, comment, defaultValue, std::move(hint), flags);
1098  }
1099 
1100  template<typename T, typename U>
1101  void property(const char* name, T& member, const char* comment,
1102  const U& defaultValue, PropertyHint&& hint = PropertyHint(),
1104  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1105  this->This()->pushObjectTrackingStore();
1106  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1107  defaultValue);
1108  this->This()->popObjectTrackingStore();
1109  } else
1110  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1111  defaultValue);
1112  }
1113 
1114  // see above. see #910
1115  template<typename T>
1116  void property(const char* name, const T& member, Setter<T> setter,
1117  const char* comment, const T& defaultValue,
1118  PropertyHint&& hint = PropertyHint(),
1120  this->template property<T, T>(name, member, setter, comment, defaultValue, std::move(hint), flags);
1121  }
1122 
1123  template<typename T, typename U>
1124  void property(const char* name, const T& member, Setter<T> setter,
1125  const char* comment, const U& defaultValue,
1126  PropertyHint&& hint = PropertyHint(),
1128  auto a = makeAccessor(member, setter);
1129  this->This()->pushObjectTrackingStore();
1130  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1131  defaultValue );
1132  this->This()->popObjectTrackingStore();
1133  }
1134 
1135  // see above. see #910
1136  template<typename T>
1137  void property(const char* name, Getter<T> getter, Setter<T> setter,
1138  const char* comment, const T& defaultValue,
1139  PropertyHint&& hint = PropertyHint(),
1141  this->template property<T, T>(name, getter, setter, comment, defaultValue, std::move(hint), flags);
1142  }
1143 
1144  template<typename T, typename U>
1145  void property(const char* name, Getter<T> getter, Setter<T> setter,
1146  const char* comment, const U& defaultValue,
1147  PropertyHint&& hint = PropertyHint(),
1149  auto a = makeAccessor(getter, setter);
1150  this->This()->pushObjectTrackingStore();
1151  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1152  defaultValue );
1153  this->This()->popObjectTrackingStore();
1154  }
1155 
1162  template<typename T>
1164  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1165  this->This()->pushObjectTrackingStore();
1166  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1167  this->This()->popObjectTrackingStore();
1168  } else
1169  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1170  }
1171 
1178  template<typename T>
1181  auto a = makeAccessor(member, setter);
1182  this->This()->pushObjectTrackingStore();
1183  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1184  this->This()->popObjectTrackingStore();
1185  }
1186 
1193  template<typename T>
1196  auto a = makeAccessor(getter, setter);
1197  this->This()->pushObjectTrackingStore();
1198  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1199  this->This()->popObjectTrackingStore();
1200  }
1201 
1202 };
1203 
1205 
1206 }
1207 
1208 #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:688
Helper to show a warning at compile time if DelegateTo is missing in IsTransparentSerializable<Delega...
Definition: RecursiveMemberReflector.h:158
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:385
Type trait that indicates whether a type should be serialized "transparently", i.e.
Definition: IsTransparentSerializable.h:81
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:1101
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:1083
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:1019
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:669
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:1012
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:554
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:947
void property(const char *name, T &member, const char *comment, const T &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1094
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
void trackObject(T &member)
Definition: RecursiveMemberReflector.h:401
Class object which supports some kind of class reflection.
Definition: Class.h:97
STL namespace.
#define MIRA_RETHROW(ex, msg)
Macro for rethrowing an exception with file and line information and for adding additional informatio...
Definition: Exception.h:144
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:85
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:1049
void chooseReflect(T &member)
Detect the members type (A1,A2,A3,B1,B2,C) and choose the appropriate function.
Definition: RecursiveMemberReflector.h:697
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:848
void pointerAbstract(T *&pointer, int typeId)
Is called if a reflected pointer is a pointer to an abstract class.
Definition: RecursiveMemberReflector.h:490
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
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:1124
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:212
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:543
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:1061
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:207
$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:310
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:451
bool query() const
Definition: RecursiveMemberReflector.h:87
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:1194
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:568
SetReflectedAsPointer()
Definition: RecursiveMemberReflector.h:122
A singleton template class that can be freely configured using policies that control the instantiatio...
Definition: Singleton.h:495
void pointerNormal(T *&pointer, int typeId)
Is called if a reflected pointer is a "normal" pointer.
Definition: RecursiveMemberReflector.h:436
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:576
void reflectPointer(T &member)
Type C: for members that are pointers.
Definition: RecursiveMemberReflector.h:653
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:1163
void reflectUnknown(T &member)
Definition: RecursiveMemberReflector.h:588
void invokePointerObject(T &member)
Is called to reflect objects of pointers.
Definition: RecursiveMemberReflector.h:812
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:1116
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:317
static void unregisterClass()
Unregisters the class.
Definition: RecursiveMemberReflector.h:532
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:1145
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:1137
void invokeMemberWithoutDefault(T &member, const ReflectMemberMeta &meta)
Delegates to invokeMember() and rethrows any occurring XMemberNotFound exception as XIO exception...
Definition: RecursiveMemberReflector.h:823
void member(const char *name, T &member, const char *comment, const U &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:998
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:958
RecursiveMemberReflectorBase()
The constructor.
Definition: RecursiveMemberReflector.h:323
#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:215
Implementation of the CreationPolicy that is used by the Singleton template.
Definition: Singleton.h:165
Base class for exceptions.
Definition: Exception.h:195
void member(const char *name, const T &member, Setter< T > setter, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:971
static OneWaySwitch & reflectedAsPointer()
For internal use only: Holds value.isOn=true, iff the type T is ever reflected as pointer with Reflec...
Definition: RecursiveMemberReflector.h:113
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
Definition: RecursiveMemberReflector.h:132
int32_t int32
Definition: Types.h:60
Holds a boost::function object to a special getter function that must meet the signature "T method()"...
Definition: GetterSetter.h:87
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:1031
void invokeMember(T &member, const ReflectMemberMeta &meta)
Is called to invoke this Reflector on the member with the specified meta information.
Definition: RecursiveMemberReflector.h:738
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:1073
void pointer(T *&pointer)
Is called if the member is a pointer.
Definition: RecursiveMemberReflector.h:409
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:1179
void reflectCollection(T &member)
Type B?c: for collection types.
Definition: RecursiveMemberReflector.h:640
static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME
Use this when a reflector needs to choose a name for serializing an object.
Definition: RecursiveMemberReflector.h:333
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
The actual invokeMember implementation that is called from invokeMember().
Definition: RecursiveMemberReflector.h:750
void enumeration(T &member)
Is called by the if the member is an enumeration.
Definition: RecursiveMemberReflector.h:365
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:603
void collection(T &member)
Is called for each complex object or array, where the IsCollection<T> trait is true_type.
Definition: RecursiveMemberReflector.h:395
void reflectComplex(T &member)
Type B1/B2: for complex types.
Definition: RecursiveMemberReflector.h:625
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:992
void member(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:980
constexpr bool hasRecursiveReflect()
Determine at compile time whether T may have members/properties:
Definition: RecursiveMemberReflector.h:173
static void registerClass()
Registers a new polymorphic class at the PolymorphPointerReflector.
Definition: RecursiveMemberReflector.h:513
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:1038
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:662
The RecursiveMemberReflector extents the RecursiveMemberReflectorBase class and implements the member...
Definition: RecursiveMemberReflector.h:938
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
#define MIRA_DEPRECATED(text, decl)
The following macro MIRA_GNUC_VERSION combines the gcc compiler version numbers in a single number...
Definition: Platform.h:132
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:120
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:352
void reflectArray(T &member)
Type A3: for arrays.
Definition: RecursiveMemberReflector.h:611
Definition: RecursiveMemberReflector.h:84
void reflectAtomic(T &member)
Type A1: for atomic members (float,int,etc.)
Definition: RecursiveMemberReflector.h:595
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:889
virtual int getTypeId() const =0
Return unique id for the class.