MIRA
AbstractReflector.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_ABSTRACTREFLECTOR_H_
48 #define _MIRA_ABSTRACTREFLECTOR_H_
49 
51 #include <utils/HasMember.h>
52 #include <utils/HasNonMember.h>
53 
54 namespace mira {
55 
57 
59 
60 namespace detail {
61 template<class Type>
62 struct ____MISSING_REFLECT_METHOD_FOR_{
63  static_assert(sizeof(Type)==0,
64  "Cannot find an (unambiguous) intrusive or nonintrusive reflect method for Type. "
65  "If Type is a class that you have implemented, then you should "
66  "implement its reflect() method. If Type is a common class or "
67  "container from an external library (including std, boost, etc.), you "
68  "probably need to include an adapter header "
69  "like #include <serialization/adapters/std/vector>. \nNote: "
70  "If you are sure a matching reflect() method exists, it might be ambiguous. "
71  "Define MIRA_SERIALIZATION_DISABLE_DETECT_REFLECT to skip MIRA's compile-time check "
72  "and see all candidates considered "
73  "(warning: will probably result in much more messy error message).");
74  static void invoke() {}
75 };
76 } // namespace
77 
78 namespace serialization {
79 
81 
82 // create detectors for reflect methods
85 
87 
88 } // namespace
90 
159 template <typename Derived>
160 class AbstractReflector : public ReflectorInterface<Derived>
161 {
162 
163 public:
164 
166 
167 public:
168 
170  template <typename T>
171  VersionType requireVersion(VersionType version, VersionType minVersion, const T* caller = NULL) {
172  VersionType v = This()->template version<T>(version);
173  checkVersion<T>(v, minVersion, false);
174  return v;
175  }
176 
177  MIRA_DEPRECATED("Please call as requireVersion<MyType>(v, minV) or requireVersion(v, minV, this)",
179  VersionType v = This()->version(version);
180  checkVersion(v, minVersion);
181  return v;
182  }
183 
185  template <typename T>
186  void requireVersion(VersionType requiredVersion, const T* caller = NULL) {
187  requireVersion<T>(requiredVersion, requiredVersion);
188  }
189 
190  MIRA_DEPRECATED("Please call as requireVersion<MyType>(v) or requireVersion(v, this)",
191  void requireVersion(VersionType requiredVersion)) {
192  requireVersion(requiredVersion, requiredVersion);
193  }
194 
196 
198  template <typename T>
200  AcceptDesiredVersion, const T* caller = NULL) {
201  VersionType v = This()->template version<T>(version, AcceptDesiredVersion());
202  checkVersion<T>(v, minVersion, true);
203  return v;
204  }
205 
207  template <typename T>
208  void requireVersion(VersionType requiredVersion, AcceptDesiredVersion, const T* caller = NULL) {
209  requireVersion<T>(requiredVersion, requiredVersion, AcceptDesiredVersion());
210  }
211 
212 private:
213 
214  template <typename T>
215  void checkVersion(VersionType version, VersionType minVersion, bool potentiallyDesired = false) {
216  if(version < minVersion)
217  MIRA_THROW(XIO, (potentiallyDesired ? "Found or desired " : "Found ") <<
218  "version for type '" << typeName<T>() <<
219  "': " << (int)version << ", but require "
220  "at least version: " << (int)minVersion);
221  }
222 
223  void checkVersion(VersionType version, VersionType minVersion) {
224  if(version < minVersion)
225  MIRA_THROW(XIO, "Found version: " << (int)version <<
226  ", but require at least version: " << (int)minVersion);
227  }
228 
229 public:
230 
232  template <typename Base>
233  void reflectBase(Base& base) {
234  this->invoke(base);
235  }
236 
237 protected:
238 
246  Derived* This()
247  {
248  // the Derived was derived from us, so we can safely cast to it ...
249  return static_cast<Derived*>(this);
250  }
251 
258  template<typename T>
259  void invoke(T& object)
260  {
261  this->This()->invokeOverwrite(object);
262  }
263 
270  template<typename T>
271  void invokeOverwrite(T& object)
272  {
273  using namespace serialization;
274 
275  typedef MIRA_HAS_MEMBER_TEMPLATE(T, reflect) hasMemberReflect;
276 #ifdef MIRA_SERIALIZATION_DISABLE_DETECT_REFLECT
277  typedef std::true_type hasNonMemberReflect;
278 #else
279  typedef MIRA_HAS_NONMEMBER_FUNCTION2(reflect, Derived&, typename boost::remove_const<T>::type&) hasNonMemberReflect;
280 #endif
281  if constexpr (hasMemberReflect::value) {
282  reflectComplexIntrusive(object);
283  }
284  else if constexpr (hasNonMemberReflect::value) {
286  }
287  else {
288  reflectMissing(object);
289  }
290  }
291 
295  template<typename T>
296  void reflectComplexIntrusive(T& object)
297  {
298  typedef typename boost::remove_const<T>::type TwithoutConst;
299  auto& nonconstObject = const_cast<TwithoutConst&>(object);
300  nonconstObject.reflect(*(this->This()));
301  }
302 
311  template<typename T>
313  {
314  // #################################################################
315  // If you get a compiler error here, you do not have specified a
316  // proper non-intrusive reflect method for the type T. You can
317  // either provide an intrusive or non-intrusive reflect method.
318  // #################################################################
319  typedef typename boost::remove_const<T>::type TwithoutConst;
320  reflect(*(this->This()), const_cast<TwithoutConst&>(object));
321  }
322 
323  template<typename T>
324  void reflectMissing(T& object)
325  {
326  typedef typename boost::remove_const<T>::type TwithoutConst;
327  mira::detail::____MISSING_REFLECT_METHOD_FOR_<TwithoutConst>::invoke();
328  }
329 };
330 
332 
333 } // namespace
334 
335 #endif // _MIRA_ABSTRACTREFLECTOR_H_
void reflectMissing(T &object)
Definition: AbstractReflector.h:324
void requireVersion(VersionType requiredVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:186
VersionType version(VersionType version, const T *caller=NULL)
Specifies the current class version and returns the version found in the data stream.
Definition: ReflectorInterface.h:242
void invokeOverwrite(T &object)
The actual invoke implementation, that may also be overwritten in derived classes to add additional f...
Definition: AbstractReflector.h:271
typename ReflectorInterface< PropertySerializer >::AcceptDesiredVersion AcceptDesiredVersion
Definition: AbstractReflector.h:195
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
#define MIRA_HAS_NONMEMBER_FUNCTION2(Identifier, ParamType0, ParamType1)
Macro checking the existence of a free function with specific parameter+return types.
Definition: HasNonMember.h:182
MIRA_DEPRECATED("Please call as requireVersion<MyType>(v, minV) or requireVersion(v, minV, this)", VersionType requireVersion(VersionType version, VersionType minVersion))
Definition: AbstractReflector.h:177
void requireVersion(VersionType requiredVersion, AcceptDesiredVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:208
MIRA_DEPRECATED("Please call as requireVersion<MyType>(v) or requireVersion(v, this)", void requireVersion(VersionType requiredVersion))
Definition: AbstractReflector.h:190
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:82
This is the public interface of all reflectors that are able to visit a class&#39; reflect() method...
Definition: ReflectorInterface.h:111
Derived * This()
"Curiously recurring template pattern" (CRTP).
Definition: AbstractReflector.h:246
void reflectComplexNonintrusive(T &object)
For classes without reflect method, where we need to look somewhere else to get the information for v...
Definition: AbstractReflector.h:312
Abstract base class for most Reflectors.
Definition: AbstractReflector.h:160
Contains the base interface of all Reflectors, Serializers, etc.
#define MIRA_HAS_MEMBER_TEMPLATE(Class, Identifier)
Definition: HasMember.h:140
#define MIRA_NONMEMBER_FUNCTION2_DETECTOR(ReturnType, FunctionName)
Definition: HasNonMember.h:111
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
VersionType requireVersion(VersionType version, VersionType minVersion, AcceptDesiredVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:199
Tag class used as parameter to ReflectorInterface::version() etc.
Definition: ReflectorInterface.h:80
void reflect(Reflector &r, LogRecord &record)
Non-intrusive reflector for LogRecord.
Definition: LoggingCore.h:137
MIRA_MEMBER_DETECTOR(mNoPublicDefaultConstructor)
typename ReflectorInterface< PropertySerializer >::VersionType VersionType
Definition: AbstractReflector.h:165
void reflectBase(Base &base)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:233
void reflectComplexIntrusive(T &object)
For classes with reflect method call their reflect method directly.
Definition: AbstractReflector.h:296
serialization::VersionType VersionType
Definition: ReflectorInterface.h:194
Macros for checking the existence of non-member functions.
Macros for checking the existence of class members.
VersionType requireVersion(VersionType version, VersionType minVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:171
void invoke(T &object)
Invokes this reflector on the specified object.
Definition: AbstractReflector.h:259