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 
50 #ifndef Q_MOC_RUN
51 #include <boost/type_traits/remove_const.hpp>
52 #include <boost/mpl/assert.hpp>
53 #endif
54 
56 #include <utils/HasMember.h>
57 #include <utils/HasNonMember.h>
58 
59 namespace mira {
60 
62 
64 
65 namespace detail {
66 template<class Type>
67 struct ____MISSING_REFLECT_METHOD_FOR_{
68  static_assert(sizeof(Type)==0,
69  "Cannot find an (unambiguous) intrusive or nonintrusive reflect method for Type. "
70  "If Type is a class that you have implemented, then you should "
71  "implement its reflect() method. If Type is a common class or "
72  "container from an external library (including std, boost, etc.), you "
73  "probably need to include an adapter header "
74  "like #include <serialization/adapters/std/vector>. \nNote: "
75  "If you are sure a matching reflect() method exists, it might be ambiguous. "
76  "Define MIRA_SERIALIZATION_DISABLE_DETECT_REFLECT to skip MIRA's compile-time check "
77  "and see all candidates considered "
78  "(warning: will probably result in much more messy error message).");
79  static void invoke() {}
80 };
81 } // namespace
82 
83 namespace serialization {
84 
86 
87 // create detectors for reflect methods
90 
92 
93 } // namespace
95 
164 template <typename Derived>
165 class AbstractReflector : public ReflectorInterface<Derived>
166 {
167 
168 public:
169 
171 
172 public:
173 
175  template <typename T>
176  VersionType requireVersion(VersionType version, VersionType minVersion, const T* caller = NULL) {
177  VersionType v = This()->template version<T>(version);
178  checkVersion<T>(v, minVersion, false);
179  return v;
180  }
181 
182  MIRA_DEPRECATED("Please call as requireVersion<MyType>(v, minV) or requireVersion(v, minV, this)",
184  VersionType v = This()->version(version);
185  checkVersion(v, minVersion);
186  return v;
187  }
188 
190  template <typename T>
191  void requireVersion(VersionType requiredVersion, const T* caller = NULL) {
192  requireVersion<T>(requiredVersion, requiredVersion);
193  }
194 
195  MIRA_DEPRECATED("Please call as requireVersion<MyType>(v) or requireVersion(v, this)",
196  void requireVersion(VersionType requiredVersion)) {
197  requireVersion(requiredVersion, requiredVersion);
198  }
199 
201 
203  template <typename T>
205  AcceptDesiredVersion, const T* caller = NULL) {
206  VersionType v = This()->template version<T>(version, AcceptDesiredVersion());
207  checkVersion<T>(v, minVersion, true);
208  return v;
209  }
210 
212  template <typename T>
213  void requireVersion(VersionType requiredVersion, AcceptDesiredVersion, const T* caller = NULL) {
214  requireVersion<T>(requiredVersion, requiredVersion, AcceptDesiredVersion());
215  }
216 
217 private:
218 
219  template <typename T>
220  void checkVersion(VersionType version, VersionType minVersion, bool potentiallyDesired = false) {
221  if(version < minVersion)
222  MIRA_THROW(XIO, (potentiallyDesired ? "Found or desired " : "Found ") <<
223  "version for type '" << typeName<T>() <<
224  "': " << (int)version << ", but require "
225  "at least version: " << (int)minVersion);
226  }
227 
228  void checkVersion(VersionType version, VersionType minVersion) {
229  if(version < minVersion)
230  MIRA_THROW(XIO, "Found version: " << (int)version <<
231  ", but require at least version: " << (int)minVersion);
232  }
233 
234 public:
235 
237  template <typename Base>
238  void reflectBase(Base& base) {
239  this->invoke(base);
240  }
241 
242 protected:
243 
251  Derived* This()
252  {
253  // the Derived was derived from us, so we can safely cast to it ...
254  return static_cast<Derived*>(this);
255  }
256 
263  template<typename T>
264  void invoke(T& object)
265  {
266  this->This()->invokeOverwrite(object);
267  }
268 
275  template<typename T>
276  void invokeOverwrite(T& object)
277  {
278  using namespace serialization;
279 
280  typedef MIRA_HAS_MEMBER_TEMPLATE(T, reflect) hasMemberReflect;
281 #ifdef MIRA_SERIALIZATION_DISABLE_DETECT_REFLECT
282  typedef std::true_type hasNonMemberReflect;
283 #else
284  typedef MIRA_HAS_NONMEMBER_FUNCTION2(reflect, Derived&, typename boost::remove_const<T>::type&) hasNonMemberReflect;
285 #endif
286  typedef typename
287  boost::mpl::eval_if<hasMemberReflect,
288  boost::mpl::identity< ReflectComplexIntrusive >, // T is a class with reflect method (Type B1)
289  //else
290  boost::mpl::eval_if<hasNonMemberReflect,
291  boost::mpl::identity< ReflectComplexNonintrusive >, // T is a class without reflect method (Type B2)
292  // else
293  boost::mpl::identity< ReflectMissing >
294  >
295  >::type chosen_reflect;
296 
297  chosen_reflect::invoke(*this->This(), object);
298  }
299 
304  template<typename T>
305  static void invoke(Derived& r, T& object) {
306  typedef typename boost::remove_const<T>::type TwithoutConst;
307  TwithoutConst& nonconstObject = const_cast<TwithoutConst&>(object);
308  nonconstObject.reflect(r);
309  }
310  };
311 
321  template<typename T>
322  static void invoke(Derived& r, T& object) {
323  // #################################################################
324  // If you get a compiler error here, you do not have specified a
325  // proper non-intrusive reflect method for the type T. You can
326  // either provide an intrusive or non-intrusive reflect method.
327  // #################################################################
328  typedef typename boost::remove_const<T>::type TwithoutConst;
329  reflect(r, const_cast<TwithoutConst&>(object));
330  }
331  };
332 
333  struct ReflectMissing {
334  template<typename T>
335  static void invoke(Derived& r, T& object) {
336  typedef typename boost::remove_const<T>::type TwithoutConst;
337  mira::detail::____MISSING_REFLECT_METHOD_FOR_<TwithoutConst>::invoke();
338  }
339  };
340 };
341 
343 
344 } // namespace
345 
346 #endif // _MIRA_ABSTRACTREFLECTOR_H_
void requireVersion(VersionType requiredVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:191
static void invoke(Derived &r, T &object)
Definition: AbstractReflector.h:335
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
ReflectorInterface< Derived >::VersionType VersionType
Definition: AbstractReflector.h:170
void invokeOverwrite(T &object)
The actual invoke implementation, that may also be overwritten in derived classes to add additional f...
Definition: AbstractReflector.h:276
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:182
void requireVersion(VersionType requiredVersion, AcceptDesiredVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:213
Definition: AbstractReflector.h:333
MIRA_DEPRECATED("Please call as requireVersion<MyType>(v) or requireVersion(v, this)", void requireVersion(VersionType requiredVersion))
Definition: AbstractReflector.h:195
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:81
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:251
Abstract base class for most Reflectors.
Definition: AbstractReflector.h:165
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:204
Tag class used as parameter to ReflectorInterface::version() etc.
Definition: ReflectorInterface.h:80
ReflectorInterface< Derived >::AcceptDesiredVersion AcceptDesiredVersion
Definition: AbstractReflector.h:200
void reflect(Reflector &r, LogRecord &record)
Non-intrusive reflector for LogRecord.
Definition: LoggingCore.h:136
MIRA_MEMBER_DETECTOR(mNoPublicDefaultConstructor)
static void invoke(Derived &r, T &object)
Definition: AbstractReflector.h:305
For classes with reflect method call their reflect method directly.
Definition: AbstractReflector.h:303
void reflectBase(Base &base)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:238
serialization::VersionType VersionType
Definition: ReflectorInterface.h:194
Macros for checking the existence of non-member functions.
Macros for checking the existence of class members.
For classes without reflect method, where we need to look somewhere else to get the information for v...
Definition: AbstractReflector.h:320
static void invoke(Derived &r, T &object)
Definition: AbstractReflector.h:322
VersionType requireVersion(VersionType version, VersionType minVersion, const T *caller=NULL)
implements ReflectorInterface (for documentation see ReflectorInterface)
Definition: AbstractReflector.h:176
void invoke(T &object)
Invokes this reflector on the specified object.
Definition: AbstractReflector.h:264