mlpack  master
serialization_shim.hpp
Go to the documentation of this file.
1 
16 #ifndef MLPACK_CORE_UTIL_SERIALIZATION_SHIM_HPP
17 #define MLPACK_CORE_UTIL_SERIALIZATION_SHIM_HPP
18 
20 #include <boost/serialization/serialization.hpp>
21 #include <boost/archive/xml_oarchive.hpp>
22 #include <type_traits>
23 
24 namespace mlpack {
25 namespace data {
26 
27 // This gives us a HasSerializeCheck<T, U> type (where U is a function pointer)
28 // we can use with SFINAE to catch when a type has a Serialize() function.
29 HAS_MEM_FUNC(Serialize, HasSerializeCheck);
30 
31 // Don't call this with a non-class. HasSerializeFunction::value is true if the
32 // type T has a static or non-static Serialize() function.
33 template<typename T>
35 {
36  static const bool value =
37  // Non-static version.
38  HasSerializeCheck<T, void(T::*)(boost::archive::xml_oarchive&,
39  const unsigned int)>::value ||
40  // Static version.
41  HasSerializeCheck<T, void(*)(boost::archive::xml_oarchive&,
42  const unsigned int)>::value;
43 };
44 
45 template<typename T>
47 {
48  // We have to handle the case where T isn't a class...
49  typedef char yes[1];
50  typedef char no [2];
51  template<typename U, typename V, typename W> struct check;
52  template<typename U> static yes& chk( // This matches classes.
53  check<U,
54  typename std::enable_if_t<std::is_class<U>::value>*,
56  template<typename > static no& chk(...); // This matches non-classes.
57 
58  static const bool value = (sizeof(chk<T>(0)) == sizeof(yes));
59 };
60 
61 // Declare the shims we need.
62 template<typename T> struct FirstShim;
63 template<typename T> struct FirstArrayShim;
64 template<typename T> struct FirstNormalArrayShim;
65 template<typename T> struct SecondShim;
66 template<typename T> struct SecondArrayShim;
67 template<typename T> struct SecondNormalArrayShim;
68 template<typename T> struct PointerShim;
69 
93 template<typename T>
95  T& t,
96  const std::string& name,
98 {
99  return FirstShim<T>(t, name);
100 }
101 
123 template<typename T>
124 inline
125 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
126 const // Imitate the boost::serialization make_nvp() function.
127 #endif
128 boost::serialization::nvp<T> CreateNVP(
129  T& t,
130  const std::string& name,
132  typename std::enable_if_t<!std::is_pointer<T>::value>* = 0)
133 {
134  return boost::serialization::make_nvp(name.c_str(), t);
135 }
136 
158 template<typename T>
159 inline
160 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
161 const
162 #endif
163 boost::serialization::nvp<PointerShim<T>*> CreateNVP(
164  T*& t,
165  const std::string& name,
167 {
168  return boost::serialization::make_nvp(name.c_str(),
169  reinterpret_cast<PointerShim<T>*&>(t));
170 }
171 
193 template<typename T>
194 inline
195 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
196 const
197 #endif
198 boost::serialization::nvp<T*> CreateNVP(
199  T*& t,
200  const std::string& name,
202 {
203  return boost::serialization::make_nvp(name.c_str(), t);
204 }
205 
213 template<typename T>
215  T* t,
216  const size_t len,
217  const std::string& name,
219 {
220  return FirstArrayShim<T>(t, len, name);
221 }
222 
230 template<typename T>
232  T* t,
233  const size_t len,
234  const std::string& name,
236 {
237  return FirstNormalArrayShim<T>(t, len, name);
238 }
239 
245 template<typename T>
246 struct FirstShim
247 {
249  FirstShim(T& t, const std::string& name) : t(t), name(name) { }
250 
251  T& t;
253 };
254 
260 template<typename T>
261 struct FirstArrayShim
262 {
264  FirstArrayShim(T* t, const size_t len, const std::string& name) :
265  t(t), len(len), name(name) { }
266 
267  T* t;
268  const size_t len;
270 };
271 
277 template<typename T>
279 {
281  FirstNormalArrayShim(T* t, const size_t len, const std::string& name) :
282  t(t), len(len), name(name) { }
283 
284  T* t;
285  const size_t len;
287 };
288 
294 template<typename T>
295 struct SecondShim
296 {
298  SecondShim(T& t) : t(t) { }
299 
301  template<typename Archive>
302  void serialize(Archive& ar, const unsigned int version)
303  {
304  t.Serialize(ar, version);
305  }
306 
307  T& t;
308 };
309 
315 template<typename T>
316 struct SecondArrayShim
317 {
319  SecondArrayShim(T* t, const size_t len) : t(t), len(len) { }
320 
322  template<typename Archive>
323  void serialize(Archive& ar, const unsigned int /* version */)
324  {
325  // Serialize each element, using the shims we already have.
326  for (size_t i = 0; i < len; ++i)
327  ar & CreateNVP(t[i], "item");
328  }
329 
330  T* t;
331  const size_t len;
332 };
333 
338 template<typename T>
340 {
342  SecondNormalArrayShim(T* t, const size_t len) : t(t), len(len) { }
343 
345  template<typename Archive>
346  void serialize(Archive& ar, const unsigned int /* version */)
347  {
348  ar & boost::serialization::make_array(t, len);
349  }
350 
351  T* t;
352  const size_t len;
353 };
354 
360 template<typename T>
361 struct PointerShim : public T { };
362 
370 template<typename Archive, typename T>
371 Archive& operator<<(Archive& ar, FirstShim<T> t)
372 {
373  SecondShim<T> sh(t.t);
374  return (ar << boost::serialization::make_nvp(t.name.c_str(), sh));
375 }
376 
384 template<typename Archive, typename T>
385 Archive& operator&(Archive& ar, FirstShim<T> t)
386 {
387  SecondShim<T> sh(t.t);
388  return (ar & boost::serialization::make_nvp(t.name.c_str(), sh));
389 }
390 
398 template<typename Archive, typename T>
399 Archive& operator>>(Archive& ar, FirstShim<T> t)
400 {
401  SecondShim<T> sh(t.t);
402  return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
403 }
404 
412 template<typename Archive, typename T>
413 Archive& operator<<(Archive& ar, FirstArrayShim<T> t)
414 {
415  SecondArrayShim<T> sh(t.t, t.len);
416  return (ar << boost::serialization::make_nvp(t.name.c_str(), sh));
417 }
418 
426 template<typename Archive, typename T>
427 Archive& operator&(Archive& ar, FirstArrayShim<T> t)
428 {
429  SecondArrayShim<T> sh(t.t, t.len);
430  return (ar & boost::serialization::make_nvp(t.name.c_str(), sh));
431 }
432 
440 template<typename Archive, typename T>
441 Archive& operator>>(Archive& ar, FirstArrayShim<T> t)
442 {
443  SecondArrayShim<T> sh(t.t, t.len);
444  return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
445 }
446 
454 template<typename Archive, typename T>
455 Archive& operator<<(Archive& ar, FirstNormalArrayShim<T> t)
456 {
457  SecondNormalArrayShim<T> sh(t.t, t.len);
458  return (ar << boost::serialization::make_nvp(t.name.c_str(), sh));
459 }
460 
468 template<typename Archive, typename T>
469 Archive& operator&(Archive& ar, FirstNormalArrayShim<T> t)
470 {
471  SecondNormalArrayShim<T> sh(t.t, t.len);
472  return (ar & boost::serialization::make_nvp(t.name.c_str(), sh));
473 }
474 
482 template<typename Archive, typename T>
483 Archive& operator>>(Archive& ar, FirstNormalArrayShim<T> t)
484 {
485  SecondNormalArrayShim<T> sh(t.t, t.len);
486  return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
487 }
488 
489 } // namespace data
490 } // namespace mlpack
491 
492 namespace boost {
493 namespace serialization {
494 
499 template<typename Archive, typename T>
500 inline void serialize(Archive& ar,
502  const BOOST_PFTO unsigned int version)
503 {
504  T* tptr = reinterpret_cast<T*>(&t);
505  tptr->Serialize(ar, version);
506 }
507 
508 } // namespace serialization
509 } // namespace boost
510 
511 #endif
FirstShim(T &t, const std::string &name)
Construct the first shim with the given object and name.
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: binarize.hpp:18
FirstShim< T > CreateNVP(T &t, const std::string &name, typename std::enable_if_t< HasSerialize< T >::value > *=0)
Call this function to produce a name-value pair; this is similar to BOOST_SERIALIZATION_NVP(), but should be used for types that have a Serialize() function (or contain a type that has a Serialize() function) instead of a serialize() function.
FirstArrayShim(T *t, const size_t len, const std::string &name)
Construct the first shim with the given objects, length, and name.
Archive & operator&(Archive &ar, FirstShim< T > t)
Catch when we call operator& with a FirstShim object.
SecondShim(T &t)
Construct the second shim. The name isn&#39;t necessary for this shim.
void serialize(Archive &ar, mlpack::data::PointerShim< T > &t, const BOOST_PFTO unsigned int version)
Catch a call to serialize() with a PointerShim, and call the Serialize() function directly...
A shim for objects in an array which do not have a Serialize() function.
A first shim for arrays without a Serialize() method.
FirstArrayShim< T > CreateArrayNVP(T *t, const size_t len, const std::string &name, typename std::enable_if_t< HasSerialize< T >::value > *=0)
Call this function to produce a name-value pair for an array; this is similar to boost::serialization...
SecondNormalArrayShim(T *t, const size_t len)
Construct the shim.
A first shim for arrays.
void serialize(Archive &ar, const unsigned int)
A wrapper for make_array().
Archive & operator>>(Archive &ar, FirstShim< T > t)
Catch when we call operator>> with a FirstShim object.
HAS_MEM_FUNC(Serialize, HasSerializeCheck)
FirstNormalArrayShim(T *t, const size_t len, const std::string &name)
Construct the first shim with the given objects, length, and name.
void serialize(Archive &ar, const unsigned int)
A wrapper for Serialize() for each element.
test cpp RESULT_VARIABLE MEX_RESULT_TRASH OUTPUT_VARIABLE MEX_OUTPUT ERROR_VARIABLE MEX_ERROR_TRASH string(REGEX MATCH"Warning: You are using"MEX_WARNING"${MEX_OUTPUT}") if(MEX_WARNING) string(REGEX REPLACE".*using [a-zA-Z]* version \"([0-9.]*)[^\"]*\".*""\\1"OTHER_COMPILER_VERSION"$
Definition: CMakeLists.txt:18
SecondArrayShim(T *t, const size_t len)
Construct the shim.
A shim for objects in an array; this is basically like the SecondShim, but for arrays that hold objec...
The first shim: simply holds the object and its name.
The second shim: wrap the call to Serialize() inside of a serialize() function, so that an archive ty...
#define BOOST_PFTO
Definition: prereqs.hpp:84
typename enable_if< B, T >::type enable_if_t
Definition: prereqs.hpp:59
void serialize(Archive &ar, const unsigned int version)
A wrapper for t.Serialize().