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 } // namespace
131 
136 MIRA_DEFINE_SERIALIZABLE_EXCEPTION(XMemberNotFound, XIO)
137 
138 
143 class XMemberNotFound_NoDefault : public XMemberNotFound
144 {
146 protected:
147  friend class ClassFactoryDefaultConstClassBuilder;
149 
150 public:
152  XMemberNotFound(ex) {}
153 
154  void raise(bool recursive = false) override
155  {
156  // The exception object is copy-initialized from *this.
157  throw *this;
158  }
159 };
160 
162 
252 template <typename Derived>
254 {
256 public:
257 
260  mCurrentMemberMeta(nullptr) {}
261 
262 protected:
263 
269  static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME = "@value";
270 
271 public:
272 
277 
287  template<typename T>
288  void atomic(T& member) {}
289 
300  template<typename T>
301  void enumeration(T& member) {
302  if constexpr(Derived::isReadOnly::value) {
303  auto val = static_cast<int32>(member);
304  this->This()->atomic(val);
305  } else {
306  int32 val;
307  this->This()->atomic(val);
308  member = static_cast<T>(val);
309  }
310  }
311 
320  template<typename T>
321  void object(T& member) {
322  this->This()->invoke(member); // invoke us recursively on the object
323  }
324 
330  template<typename T>
331  void collection(T& member) {
332  this->This()->object(member); // default impl calls object()
333  }
334 
335 
336  template<typename T>
337  void trackObject(T& member) {}
338 
344  template<typename T>
345  void pointer(T*& pointer)
346  {
347  // this will instantiate the SetReflectedAsPointer during startup
348  // which will set reflectedAsPointer<T,Derived>::value to true,
349  // and mark that T was reflected as pointer by Derived at least once.
351  singleton::CreateStatic>::instance();
352 
353  if constexpr (std::is_base_of_v<mira::Object, T>) {
355  }
356  else if constexpr (std::is_abstract_v<T>) {
358  }
359  else {
361  }
362  }
363 
371  template<typename T>
372  void pointerNormal(T*& pointer, int typeId)
373  {
374  if (pointer != NULL) // delegate serialization of the actual object recursively
375  this->This()->invokePointerObject(*pointer);
376  }
377 
386  template<typename T>
388  {
389  if (pointer != NULL) { // delegate serialization of the actual object recursively
390 
391  try {
392  // obtain a special polymorph pointer serializer for the derived type
393  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
394 
395  typename OurRegistrar::ReflectorRef r =
396  OurRegistrar::instance().getPolymorphicPointerReflector(typeId);
397 
398  // deserialize the content recursively
399  r.invoke(*this->This(), serialization::void_upcast(pointer));
400  }
401  catch (XPolymorphicPointerReflectorNotRegistered&) {
402  const ReflectMemberMeta& meta = getCurrentMemberMeta();
403  const Class& c = pointer->getClass();
404  MIRA_THROW(XIO,
405  "Cannot reflect the polymorphic member pointer '"
406  << meta.name << "'. The class '" << c.getIdentifier()
407  << "' was not registered with this serializer '" << typeName<Derived>()
408  << "'"
409 #ifndef MIRA_REGISTER_LEGACY_SERIALIZERS
410  << " (Registration with legacy serializers must be explicitly enabled"
411  " by activating the option REGISTER_LEGACY_SERIALIZERS"
412  " [GlobalConfig, requires recompilation])";
413 #endif
414  );
415  }
416  }
417  }
418 
425  template<typename T>
427  {
428  if (pointer != NULL) // delegate serialization of the actual object recursively
429  this->This()->invokePointerObject(*pointer);
430  }
431 
433 
434 public:
435 
448  template<typename T>
449  static void registerClass()
450  {
451  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
452 
453  if(!OurRegistrar::isDestroyed())
454  OurRegistrar::instance().template registerClass<T>();
455  }
456 
467  template<typename T>
468  static void unregisterClass()
469  {
470  typedef serialization::PolymorphicPointerReflectorRegistrar<Derived> OurRegistrar;
471  if(!OurRegistrar::isDestroyed())
472  OurRegistrar::instance().template unregisterClass<T>();
473  }
474 public:
475 
479  [[nodiscard]] const ReflectMemberMeta& getCurrentMemberMeta() const
480  {
481  assert(mCurrentMemberMeta!=NULL);
482  return *mCurrentMemberMeta;
483  }
484 
490  [[nodiscard]] const std::string& getCurrentMemberFullID() const
491  {
492  assert(this->usesHumanReadableIDs());
493  return mCurrentMemberFullID;
494  }
495 
496 public:
497 
503  template<typename T>
504  static bool isReflectedAsPointer()
505  {
506  return serialization::reflectedAsPointer<T, Derived>().query();
507  }
508 
509 protected:
511  template<typename T>
513  {
514  if constexpr (IsObjectTrackable<T>::value)
515  this->This()->trackObject(member);
516  }
517 
518  // The following structs implement different invoke methods for each of
519  // the member types (A1-3, B1-2, C). The member types are detected in
520  // the invoke method above which delegates to the invoke method
521  // of the correct struct below.
522 
523  template<typename T>
525  {
526  static_assert(sizeof(T) == 0, "Trying to reflect unknown type.");
527  }
528 
530  template<typename T>
532  {
533  this->This()->invokeTrackObject(member);
534  this->This()->atomic(member);
535  }
536 
538  template<typename T>
540  {
541  this->This()->invokeTrackObject(member);
542  this->This()->enumeration(member);
543  }
544 
546  template<typename T>
548  {
549  this->This()->invokeTrackObject(member);
550  std::size_t size = sizeof(member)
551  / (static_cast<const char*>(static_cast<const void*>(&member[1]))
552  - static_cast<const char*>(static_cast<const void*>(&member[0])));
553 
554  typedef typename std::remove_extent<T>::type ItemType;
555  serialization::Array<ItemType> array(member, size);
556  reflectCollection(array);
557  }
558 
560  template<typename T>
562  {
563  this->This()->invokeTrackObject(member);
564  typedef typename std::remove_cv<T>::type Type;
565  static_assert(!IsCollection<Type>::value,
566  "Trying to call reflectComplex<T>() with IsCollection<T> == true "
567  "- something is wrong.");
569  this->This()->invoke(member);
570  else
571  this->This()->object(member);
572  }
573 
575  template<typename T>
577  {
578  this->This()->invokeTrackObject(member);
579  typedef typename std::remove_cv<T>::type Type;
581  static_assert(!isTransparent::value,
582  "Trying to call reflectCollection<T>() with IsTransparentSerializable<T> == "
583  "true - something is wrong.");
584  this->This()->collection(member);
585  }
586 
588  template<typename T>
590  {
591  this->This()->pointer(member);
592  }
593 
594  // The following ReflectPointerXXX structs are used by our pointer() method
595 
597  template<typename T>
599  {
600  this->This()->pointerNormal(member, typeId<T>());
601  }
602 
604  template<typename T>
606  {
607  int typeId = -1;
608 
609  if (member != nullptr) {
610  // we have an object, so we can obtain its class information
611  const Class& c = member->getClass();
612  typeId = c.getTypeId();
613  }
614 
615  // call pointerPolymorphic()
616  this->This()->pointerPolymorphic(member, typeId);
617  }
618 
623  template<typename T>
625  {
626  this->This()->pointerAbstract(member, typeId<T>());
627  }
628 
632  template<typename T>
634  {
635  using Type = typename std::remove_cv<T>::type;
636  if constexpr (std::is_pointer_v<Type>) {
638  } // T is a pointer (Type C)
639  else if constexpr (IsAtomicSerializable<Type>::value) {
641  } // atomic (Type A1)
642  else if constexpr (std::is_class_v<Type>) {
643  if constexpr (IsCollection<Type>::value) {
645  } // T is a collection (Type B?c)
646  else {
648  } // T is a complex class (Type B1/B2)
649  }
650  else if constexpr (std::is_enum_v<Type>) {
652  } // enum (Type A2)
653  else if constexpr (std::is_array_v<Type>) {
655  } // T is no pointer, no class --> must be atomic or enum
656  else {
658  }
659  }
660 
661 public:
662 
673  template<typename T>
674  void invokeMember(T& member, const ReflectMemberMeta& meta)
675  {
676  this->This()->invokeMemberOverwrite(member, meta);
677  }
678 
685  template<typename T>
687  {
688  // store previous meta (it is restored at the end of this method
689  // and therefore implements a stack, where mCurrentMemberMeta is
690  // the top element in the stack)
691  const ReflectMemberMeta* prevMeta = mCurrentMemberMeta;
692 
693  // do the same to create a stack of the full human readable object
694  // id (however, only do it, if our final reflector supports human
695  // readable id's, otherwise skip this step since it hurts the
696  // performance
697  std::string prevFullID;
698  if(this->usesHumanReadableIDs()) {
699  prevFullID = mCurrentMemberFullID;
700 
701  // "push" new full id
702  if(mCurrentMemberFullID.empty()) {
703  if(meta.id==nullptr)
704  MIRA_THROW(XLogical, "Top-level member cannot be 'inline'. "
705  "It must have an ID != NULL!");
706  mCurrentMemberFullID=meta.id;
707  } else if(meta.id!=nullptr)
708  mCurrentMemberFullID = mCurrentMemberFullID + "." + meta.id;
709  }
710 
711  // "push" current meta (but only if member is not transparent, which is
712  // indicated by an id of NULL)
713  if(meta.id != nullptr)
714  mCurrentMemberMeta = &meta;
715 
716  // Choose the type of the member and select the
717  // correct ReflectXYZ struct for that type at compile type.
718  // Then call the invoke method of that struct.
719  // (The different structures and their invoke methods are defined
720  // above)
721  try
722  {
724  }
725  catch(...)
726  {
727  // "pop" our id
728  if(this->usesHumanReadableIDs())
729  mCurrentMemberFullID=prevFullID;
730  // "pop" our meta data stack.
731  mCurrentMemberMeta = prevMeta;
732  // and throw
733  throw;
734  }
735 
736  // "pop" our id
737  if(this->usesHumanReadableIDs())
738  mCurrentMemberFullID=prevFullID;
739  // "pop" our meta data stack.
740  mCurrentMemberMeta = prevMeta;
741  }
742 
747  template<typename T>
749  {
751  }
752 
753 
758  template<typename T>
760  {
761  try {
762  this->invokeMember(member,meta);
763  } catch (XMemberNotFound& ex) {
764  throw XMemberNotFound_NoDefault(ex);
765  // transform exception to avoid catching it
766  // in upper levels, where it might be shadowed
767  // if a default value is given there (see #685)
768  } catch(Exception& ex) {
769  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
770  throw;
771 
772  MIRA_RETHROW(ex, "while " <<
773  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
774  " '" << meta.getName() << "'");
775  }
776  }
777 
783  template<typename T, typename U>
785  const U& defaultValue)
786  {
787  try {
788  this->invokeMember(member,meta);
789  } catch (XMemberNotFound_NoDefault&) {
790  throw; // must not handle this
791  } catch (XMemberNotFound&) {
792  if constexpr(!Derived::isReadOnly::value) {
793  MIRA_LOG(NOTICE) << "No value given for '" << meta.name << "', "
794  "using the default value instead.";
795 
796  // #############################################################
797  // If you get a compiler error here, your default value does not
798  // match to your member type and cannot be casted. Make sure
799  // that the data type of your default value can be casted to
800  // the data type of your member!
801  // #############################################################
802  try {
803  member=defaultValue;
804  } catch(Exception& ex) {
805  MIRA_RETHROW(ex, "while default-initializing '" << meta.getName() << "'");
806  }
807  }
808  } catch(Exception& ex) {
809  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
810  throw;
811 
812  MIRA_RETHROW(ex, "while " <<
813  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
814  " '" << meta.getName() << "'");
815  }
816  }
817 
824  template<typename T>
826  const serialization::IgnoreMissing& defaultValue)
827  {
828  try {
829  this->invokeMember(member,meta);
830  } catch (XMemberNotFound_NoDefault&) {
831  throw; // must not handle this
832  } catch (XMemberNotFound&) {
833  // IGNORE
834  } catch(Exception& ex) {
835  if (meta.getName() == MIRA_REFLECTOR_TOPLEVEL_NAME) // no extra info
836  throw;
837 
838  MIRA_RETHROW(ex, "while " <<
839  (Derived::isReadOnly::value ? "serializing" : "deserializing") <<
840  " '" << meta.getName() << "'");
841  }
842  }
843 
845 
846 private:
847 
848  const ReflectMemberMeta* mCurrentMemberMeta;
849  std::string mCurrentMemberFullID;
850 
851 };
852 
854 
873 template <typename Derived>
875 {
876 public:
877 
878  // implement our supported visiting methods of the ReflectorInterface
879  // note: the documentation of the following methods is inherited from
880  // ReflectorInterface by Doxygen
881 
882  template<typename T>
883  void member(const char* name, T& member, const char* comment,
885  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
886  this->This()->pushObjectTrackingStore();
887  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
888  this->This()->popObjectTrackingStore();
889  } else
890  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
891  }
892 
893  template<typename T>
894  void member(const char* name, const std::string& id, T& member,
895  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
896  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
897  this->This()->pushObjectTrackingStore();
898  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
899  comment) );
900  this->This()->popObjectTrackingStore();
901  } else
902  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(),
903  comment) );
904  }
905 
906  template<typename T>
907  void member(const char* name, const T& member, Setter<T> setter,
908  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
909  auto a = makeAccessor(member, setter);
910  this->This()->pushObjectTrackingStore();
911  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
912  this->This()->popObjectTrackingStore();
913  }
914 
915  template<typename T>
916  void member(const char* name, Getter<T> getter, Setter<T> setter,
917  const char* comment, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
918  auto a = makeAccessor(getter, setter);
919  this->This()->pushObjectTrackingStore();
920  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
921  this->This()->popObjectTrackingStore();
922  }
923 
924  // avoid member("MyMember", member, "my member", {}) (most probably meant to
925  // set default-initialized object as deserialization default) unambiguously matching
926  // Reflector::member(name, member, comment, flags). see #910
927  template<typename T>
928  void member(const char* name, T& member, const char* comment,
929  const T& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
930  this->template member<T, T>(name, member, comment, defaultValue, flags);
931  }
932 
933  template<typename T, typename U>
934  void member(const char* name, T& member, const char* comment,
935  const U& defaultValue, ReflectCtrlFlags flags = REFLECT_CTRLFLAG_NONE) {
936  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
937  this->This()->pushObjectTrackingStore();
938  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
939  defaultValue);
940  this->This()->popObjectTrackingStore();
941  } else
942  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
943  defaultValue);
944  }
945 
946  // see above. see #910
947  template<typename T>
948  void member(const char* name, const T& member, Setter<T> setter,
949  const char* comment, const T& defaultValue,
951  this->template member<T, T>(name, member, setter, comment, defaultValue, flags);
952  }
953 
954  template<typename T, typename U>
955  void member(const char* name, const T& member, Setter<T> setter,
956  const char* comment, const U& defaultValue,
958  auto a = makeAccessor(member, setter);
959  this->This()->pushObjectTrackingStore();
960  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
961  defaultValue );
962  this->This()->popObjectTrackingStore();
963  }
964 
965  // see above. see #910
966  template<typename T>
967  void member(const char* name, Getter<T> getter, Setter<T> setter,
968  const char* comment, const T& defaultValue,
970  this->template member<T, T>(name, getter, setter, comment, defaultValue, flags);
971  }
972 
973  template<typename T, typename U>
974  void member(const char* name, Getter<T> getter, Setter<T> setter,
975  const char* comment, const U& defaultValue,
977  auto a = makeAccessor(getter, setter);
978  this->This()->pushObjectTrackingStore();
979  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
980  defaultValue );
981  this->This()->popObjectTrackingStore();
982  }
983 
984  template<typename T>
985  void property(const char* name, T& member, const char* comment,
986  PropertyHint&& hint = PropertyHint(),
988  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
989  this->This()->pushObjectTrackingStore();
990  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
991  this->This()->popObjectTrackingStore();
992  } else
993  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, name, comment) );
994  }
995 
996  template<typename T>
997  void property(const char* name, const std::string& id, T& member,
998  const char* comment, PropertyHint&& hint = PropertyHint(),
1000  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1001  this->This()->pushObjectTrackingStore();
1002  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
1003  this->This()->popObjectTrackingStore();
1004  } else
1005  this->invokeMemberWithoutDefault(member, ReflectMemberMeta(name, id.c_str(), comment) );
1006  }
1007 
1008  template<typename T>
1009  void property(const char* name, const T& member, Setter<T> setter,
1010  const char* comment, PropertyHint&& hint = PropertyHint(),
1012  auto a = makeAccessor(member, setter);
1013  this->This()->pushObjectTrackingStore();
1014  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
1015  this->This()->popObjectTrackingStore();
1016  }
1017 
1018  template<typename T>
1019  void property(const char* name, Getter<T> getter, Setter<T> setter,
1020  const char* comment, PropertyHint&& hint = PropertyHint(),
1022  auto a = makeAccessor(getter, setter);
1023  this->This()->pushObjectTrackingStore();
1024  this->invokeMemberWithoutDefault(a, ReflectMemberMeta(name, name, comment) );
1025  this->This()->popObjectTrackingStore();
1026  }
1027 
1028  // see above. see #910
1029  template<typename T>
1030  void property(const char* name, T& member, const char* comment,
1031  const T& defaultValue, PropertyHint&& hint = PropertyHint(),
1033  this->template property<T, T>(name, member, comment, defaultValue, std::move(hint), flags);
1034  }
1035 
1036  template<typename T, typename U>
1037  void property(const char* name, T& member, const char* comment,
1038  const U& defaultValue, PropertyHint&& hint = PropertyHint(),
1040  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1041  this->This()->pushObjectTrackingStore();
1042  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1043  defaultValue);
1044  this->This()->popObjectTrackingStore();
1045  } else
1046  this->invokeMemberWithDefault(member, ReflectMemberMeta(name, name, comment),
1047  defaultValue);
1048  }
1049 
1050  // see above. see #910
1051  template<typename T>
1052  void property(const char* name, const T& member, Setter<T> setter,
1053  const char* comment, const T& defaultValue,
1054  PropertyHint&& hint = PropertyHint(),
1056  this->template property<T, T>(name, member, setter, comment, defaultValue, std::move(hint), flags);
1057  }
1058 
1059  template<typename T, typename U>
1060  void property(const char* name, const T& member, Setter<T> setter,
1061  const char* comment, const U& defaultValue,
1062  PropertyHint&& hint = PropertyHint(),
1064  auto a = makeAccessor(member, setter);
1065  this->This()->pushObjectTrackingStore();
1066  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1067  defaultValue );
1068  this->This()->popObjectTrackingStore();
1069  }
1070 
1071  // see above. see #910
1072  template<typename T>
1073  void property(const char* name, Getter<T> getter, Setter<T> setter,
1074  const char* comment, const T& defaultValue,
1075  PropertyHint&& hint = PropertyHint(),
1077  this->template property<T, T>(name, getter, setter, comment, defaultValue, std::move(hint), flags);
1078  }
1079 
1080  template<typename T, typename U>
1081  void property(const char* name, Getter<T> getter, Setter<T> setter,
1082  const char* comment, const U& defaultValue,
1083  PropertyHint&& hint = PropertyHint(),
1085  auto a = makeAccessor(getter, setter);
1086  this->This()->pushObjectTrackingStore();
1087  this->invokeMemberWithDefault(a, ReflectMemberMeta(name, name, comment),
1088  defaultValue );
1089  this->This()->popObjectTrackingStore();
1090  }
1091 
1098  template<typename T>
1100  if (flags & REFLECT_CTRLFLAG_TEMP_TRACKING) {
1101  this->This()->pushObjectTrackingStore();
1102  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1103  this->This()->popObjectTrackingStore();
1104  } else
1105  this->invokeMember(member, ReflectMemberMeta(nullptr, nullptr, "") );
1106  }
1107 
1114  template<typename T>
1117  auto a = makeAccessor(member, setter);
1118  this->This()->pushObjectTrackingStore();
1119  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1120  this->This()->popObjectTrackingStore();
1121  }
1122 
1129  template<typename T>
1132  auto a = makeAccessor(getter, setter);
1133  this->This()->pushObjectTrackingStore();
1134  this->invokeMember(a, ReflectMemberMeta(nullptr, nullptr, "") );
1135  this->This()->popObjectTrackingStore();
1136  }
1137 
1138 };
1139 
1141 
1142 }
1143 
1144 #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:624
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:321
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:1037
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:1019
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:955
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:605
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:948
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:490
void member(const char *name, T &member, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:883
void property(const char *name, T &member, const char *comment, const T &defaultValue, PropertyHint &&hint=PropertyHint(), ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:1030
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:529
void trackObject(T &member)
Definition: RecursiveMemberReflector.h:337
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: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: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:985
void chooseReflect(T &member)
Detect the members type (A1,A2,A3,B1,B2,C) and choose the appropriate function.
Definition: RecursiveMemberReflector.h:633
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:784
void pointerAbstract(T *&pointer, int typeId)
Is called if a reflected pointer is a pointer to an abstract class.
Definition: RecursiveMemberReflector.h:426
#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:1060
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:148
const ReflectMemberMeta & getCurrentMemberMeta() const
Returns the meta-information of the current member that is reflected.
Definition: RecursiveMemberReflector.h:479
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:997
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:143
$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:387
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:1130
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:504
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:372
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:512
void reflectPointer(T &member)
Type C: for members that are pointers.
Definition: RecursiveMemberReflector.h:589
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:1099
void reflectUnknown(T &member)
Definition: RecursiveMemberReflector.h:524
void invokePointerObject(T &member)
Is called to reflect objects of pointers.
Definition: RecursiveMemberReflector.h:748
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:1052
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:253
static void unregisterClass()
Unregisters the class.
Definition: RecursiveMemberReflector.h:468
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:1081
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:1073
void invokeMemberWithoutDefault(T &member, const ReflectMemberMeta &meta)
Delegates to invokeMember() and rethrows any occurring XMemberNotFound exception as XIO exception...
Definition: RecursiveMemberReflector.h:759
void member(const char *name, T &member, const char *comment, const U &defaultValue, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:934
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:894
RecursiveMemberReflectorBase()
The constructor.
Definition: RecursiveMemberReflector.h:259
#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:151
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:907
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
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:967
void invokeMember(T &member, const ReflectMemberMeta &meta)
Is called to invoke this Reflector on the member with the specified meta information.
Definition: RecursiveMemberReflector.h:674
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:1009
void pointer(T *&pointer)
Is called if the member is a pointer.
Definition: RecursiveMemberReflector.h:345
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:1115
void reflectCollection(T &member)
Type B?c: for collection types.
Definition: RecursiveMemberReflector.h:576
static constexpr auto MIRA_REFLECTOR_TOPLEVEL_NAME
Use this when a reflector needs to choose a name for serializing an object.
Definition: RecursiveMemberReflector.h:269
void invokeMemberOverwrite(T &member, const ReflectMemberMeta &meta)
The actual invokeMember implementation that is called from invokeMember().
Definition: RecursiveMemberReflector.h:686
void enumeration(T &member)
Is called by the if the member is an enumeration.
Definition: RecursiveMemberReflector.h:301
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:539
void collection(T &member)
Is called for each complex object or array, where the IsCollection<T> trait is true_type.
Definition: RecursiveMemberReflector.h:331
void reflectComplex(T &member)
Type B1/B2: for complex types.
Definition: RecursiveMemberReflector.h:561
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:928
void member(const char *name, Getter< T > getter, Setter< T > setter, const char *comment, ReflectCtrlFlags flags=REFLECT_CTRLFLAG_NONE)
Definition: RecursiveMemberReflector.h:916
static void registerClass()
Registers a new polymorphic class at the PolymorphPointerReflector.
Definition: RecursiveMemberReflector.h:449
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:974
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:598
The RecursiveMemberReflector extents the RecursiveMemberReflectorBase class and implements the member...
Definition: RecursiveMemberReflector.h:874
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: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:288
void reflectArray(T &member)
Type A3: for arrays.
Definition: RecursiveMemberReflector.h:547
Definition: RecursiveMemberReflector.h:84
void reflectAtomic(T &member)
Type A1: for atomic members (float,int,etc.)
Definition: RecursiveMemberReflector.h:531
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:825
virtual int getTypeId() const =0
Return unique id for the class.