[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