[mlpack-git] master: Add shims for arrays. (036ed5c)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Fri Jul 10 18:59:45 EDT 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/4a97187bbba7ce8a6191b714949dd818ef0f37d2...e5905e62c15d1bcff21e6359b11efcd7ab6d7ca0

>---------------------------------------------------------------

commit 036ed5c488b035cea3ba5d9f53d1959881d75074
Author: ryan <ryan at ratml.org>
Date:   Mon Apr 20 17:19:54 2015 -0400

    Add shims for arrays.


>---------------------------------------------------------------

036ed5c488b035cea3ba5d9f53d1959881d75074
 src/mlpack/core/data/serialization_shim.hpp | 225 +++++++++++++++++++++++++++-
 1 file changed, 224 insertions(+), 1 deletion(-)

diff --git a/src/mlpack/core/data/serialization_shim.hpp b/src/mlpack/core/data/serialization_shim.hpp
index ac046c0..56c0e24 100644
--- a/src/mlpack/core/data/serialization_shim.hpp
+++ b/src/mlpack/core/data/serialization_shim.hpp
@@ -24,7 +24,11 @@ HAS_MEM_FUNC(Serialize, HasSerialize);
 
 // Declare the shims we need.
 template<typename T> class FirstShim;
+template<typename T> class FirstArrayShim;
+template<typename T> class FirstNormalArrayShim;
 template<typename T> class SecondShim;
+template<typename T> class SecondArrayShim;
+template<typename T> class SecondNormalArrayShim;
 
 /**
  * Call this function to produce a name-value pair; this is similar to
@@ -132,6 +136,62 @@ boost::serialization::nvp<T> CreateNVP(
 }
 
 /**
+ * Call this function to produce a name-value pair for an array; this is similar
+ * to boost::serialization::make_array(), but provides a nicer wrapper, allows
+ * types that have a Serialize() function, and allows you to give a name to your
+ * array.  This particular overload is used by classes that have a Serialize()
+ * function.
+ */
+template<typename T>
+inline FirstArrayShim<T> CreateArrayNVP(
+    T* t,
+    const size_t len,
+    const std::string& name,
+    typename boost::enable_if<boost::is_class<T>>::type* = 0,
+    typename boost::enable_if<HasSerialize<T,
+        void(T::*)(boost::archive::xml_oarchive&, const unsigned int)>>::
+        type* = 0)
+{
+  return FirstArrayShim<T>(t, len, name);
+}
+
+/**
+ * Call this function to produce a name-value pair for an array; this is similar
+ * to boost::serialization::make_array(), but provides a nicer wrapper, allows
+ * types that have a Serialize() function, and allows you to give a name to your
+ * array.  This particular overload is used by classes that do not have a
+ * Serialize() function.
+ */
+template<typename T>
+inline FirstNormalArrayShim<T> CreateArrayNVP(
+    T* t,
+    const size_t len,
+    const std::string& name,
+    typename boost::enable_if<boost::is_class<T>>::type* = 0,
+    typename boost::disable_if<HasSerialize<T,
+        void(T::*)(boost::archive::xml_oarchive&, const unsigned int)>>::
+        type* = 0)
+{
+  return FirstNormalArrayShim<T>(t, len, name);
+}
+
+/**
+ * Call this function to produce a name-value pair for an array; this is similar
+ * to boost::serialization::make_array(), but provides a nicer wrapper, allows
+ * types that have a Serialize() function, and allows you to give a name to your
+ * array.  This particular overload is used by primitive types.
+ */
+template<typename T>
+inline FirstNormalArrayShim<T> CreateArrayNVP(
+    T* t,
+    const size_t len,
+    const std::string& name,
+    typename boost::disable_if<boost::is_class<T>>::type* = 0)
+{
+  return FirstNormalArrayShim<T>(t, len, name);
+}
+
+/**
  * The first shim: simply holds the object and its name.  This shim's purpose is
  * to be caught by our overloads of operator<<, operator&, and operator>>, which
  * then creates a second shim.
@@ -147,6 +207,40 @@ struct FirstShim
 };
 
 /**
+ * A first shim for arrays.  This shim's purpose is to be caught by our
+ * overloads of operator<<, operator&, and operator>>, which then creates a
+ * second shim.
+ */
+template<typename T>
+struct FirstArrayShim
+{
+  //! Construct the first shim with the given objects, length, and name.
+  FirstArrayShim(T* t, const size_t len, const std::string& name) :
+      t(t), len(len), name(name) { }
+
+  T* t;
+  const size_t len;
+  const std::string& name;
+};
+
+/**
+ * A first shim for arrays without a Serialize() method.  This shim's purpose is
+ * to be caught by our overloads of operator<<, operator&, and operator>>, which
+ * then creates a second shim.
+ */
+template<typename T>
+struct FirstNormalArrayShim
+{
+  //! Construct the first shim with the given objects, length, and name.
+  FirstNormalArrayShim(T* t, const size_t len, const std::string& name) :
+      t(t), len(len), name(name) { }
+
+  T* t;
+  const size_t len;
+  const std::string& name;
+};
+
+/**
  * The second shim: wrap the call to Serialize() inside of a serialize()
  * function, so that an archive type can call serialize() on a SecondShim object
  * and this gets forwarded correctly to our object's Serialize() function.
@@ -168,6 +262,51 @@ struct SecondShim
 };
 
 /**
+ * A shim for objects in an array; this is basically like the SecondShim, but
+ * for arrays that hold objects that have Serialize() methods instead of
+ * serialize() methods.
+ */
+template<typename T>
+struct SecondArrayShim
+{
+  //! Construct the shim.
+  SecondArrayShim(T* t, const size_t len) : t(t), len(len) { }
+
+  //! A wrapper for Serialize() for each element.
+  template<typename Archive>
+  void serialize(Archive& ar, const unsigned int version)
+  {
+    // Serialize each element, using the shims we already have.
+    for (size_t i = 0; i < len; ++i)
+      ar & CreateNVP(t[i], "item");
+  }
+
+  T* t;
+  const size_t len;
+};
+
+/**
+ * A shim for objects in an array which do not have a Serialize() function.
+ * This is like the SecondShim class.
+ */
+template<typename T>
+struct SecondNormalArrayShim
+{
+  //! Construct the shim.
+  SecondNormalArrayShim(T* t, const size_t len) : t(t), len(len) { }
+
+  //! A wrapper for make_array().
+  template<typename Archive>
+  void serialize(Archive& ar, const unsigned int version)
+  {
+    ar & boost::serialization::make_array(t, len);
+  }
+
+  T* t;
+  const size_t len;
+};
+
+/**
  * Catch when we call operator<< with a FirstShim object.  In this case, we make
  * the second-level shim and use it.  Note that this second-level shim can be
  * used as an lvalue, which is what's necessary for this whole thing to work.
@@ -196,7 +335,7 @@ Archive& operator&(Archive& ar, FirstShim<T> t)
 }
 
 /**
- * Catch when we call operator<< with a FirstShim object.  In this case, we make
+ * Catch when we call operator>> with a FirstShim object.  In this case, we make
  * the second-level shim and use it.  Note that this second-level shim can be
  * used as an lvalue, which is what's necessary for this whole thing to work.
  * The first-level shim can't be an lvalue (this is why we need two levels of
@@ -209,6 +348,90 @@ Archive& operator>>(Archive& ar, FirstShim<T> t)
   return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
 }
 
+/**
+ * Catch when we call operator<< with a FirstArrayShim object.  In this case, we
+ * make the second-level array shim and use it.  Note that this second-level
+ * shim can be used as an lvalue, which is what's necessary for this whole thing
+ * to work.  The first-level shim can't be an lvalue (this is why we need two
+ * levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator<<(Archive& ar, FirstArrayShim<T> t)
+{
+  SecondArrayShim<T> sh(t.t, t.len);
+  return (ar << boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
+/**
+ * Catch when we call operator& with a FirstArrayShim object.  In this case, we
+ * make the second-level array shim and use it.  Note that this second-level
+ * shim can be used as an lvalue, which is what's necessary for this whole thing
+ * to work.  The first-level shim can't be an lvalue (this is why we need two
+ * levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator&(Archive& ar, FirstArrayShim<T> t)
+{
+  SecondArrayShim<T> sh(t.t, t.len);
+  return (ar & boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
+/**
+ * Catch when we call operator>> with a FirstArrayShim object.  In this case, we
+ * make the second-level array shim and use it.  Note that this second-level
+ * shim can be used as an lvalue, which is what's necessary for this whole thing
+ * to work.  The first-level shim can't be an lvalue (this is why we need two
+ * levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator>>(Archive& ar, FirstArrayShim<T> t)
+{
+  SecondArrayShim<T> sh(t.t, t.len);
+  return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
+/**
+ * Catch when we call operator<< with a FirstNormalArrayShim object.  In this
+ * case, we make the second-level array shim and use it.  Note that this
+ * second-level shim can be used as an lvalue, which is necessary if we want to
+ * use make_nvp() safely.  The first-level shim can't be an lvalue (this is why
+ * we need two levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator<<(Archive& ar, FirstNormalArrayShim<T> t)
+{
+  SecondNormalArrayShim<T> sh(t.t, t.len);
+  return (ar << boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
+/**
+ * Catch when we call operator& with a FirstNormalArrayShim object.  In this
+ * case, we make the second-level array shim and use it.  Note that this
+ * second-level shim can be used as an lvalue, which is necessary if we want to
+ * use make_nvp() safely.  The first-level shim can't be an lvalue (this is why
+ * we need two levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator&(Archive& ar, FirstNormalArrayShim<T> t)
+{
+  SecondNormalArrayShim<T> sh(t.t, t.len);
+  return (ar & boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
+/**
+ * Catch when we call operator>> with a FirstNormalArrayShim object.  In this
+ * case, we make the second-level array shim and use it.  Note that this
+ * second-level shim can be used as an lvalue, which is necessary if we want to
+ * use make_nvp() safely.  The first-level shim can't be an lvalue (this is why
+ * we need two levels of shims).
+ */
+template<typename Archive, typename T>
+Archive& operator>>(Archive& ar, FirstNormalArrayShim<T> t)
+{
+  SecondNormalArrayShim<T> sh(t.t, t.len);
+  return (ar >> boost::serialization::make_nvp(t.name.c_str(), sh));
+}
+
 } // namespace data 
 } // namespace mlpack
 



More information about the mlpack-git mailing list