[mlpack-git] master: Refactor serialization shim to handle static methods. Also make it shorter by removing a bunch of CreateNVP() overloads. (494a04c)
gitdub at big.cc.gt.atl.ga.us
gitdub at big.cc.gt.atl.ga.us
Mon Jul 13 04:04:38 EDT 2015
Repository : https://github.com/mlpack/mlpack
On branch : master
Link : https://github.com/mlpack/mlpack/compare/8b2ca720828224607c70d2b539c43aecf8f4ec32...b4659b668021db631b3c8a48e3d735b513706fdc
>---------------------------------------------------------------
commit 494a04c6e87dbb075f14d1fcf1806500e150db0c
Author: Ryan Curtin <ryan at ratml.org>
Date: Sat Jul 11 21:57:54 2015 +0000
Refactor serialization shim to handle static methods.
Also make it shorter by removing a bunch of CreateNVP() overloads.
>---------------------------------------------------------------
494a04c6e87dbb075f14d1fcf1806500e150db0c
src/mlpack/core/data/serialization_shim.hpp | 154 ++++++++--------------------
1 file changed, 42 insertions(+), 112 deletions(-)
diff --git a/src/mlpack/core/data/serialization_shim.hpp b/src/mlpack/core/data/serialization_shim.hpp
index fd38adf..99fbd85 100644
--- a/src/mlpack/core/data/serialization_shim.hpp
+++ b/src/mlpack/core/data/serialization_shim.hpp
@@ -18,9 +18,39 @@
namespace mlpack {
namespace data {
-// This gives us a HasSerialize<T, U> type (where U is a function pointer) we
-// can use with SFINAE to catch when a type has a Serialize() function.
-HAS_MEM_FUNC(Serialize, HasSerialize);
+// This gives us a HasSerializeCheck<T, U> type (where U is a function pointer)
+// we can use with SFINAE to catch when a type has a Serialize() function.
+HAS_MEM_FUNC(Serialize, HasSerializeCheck);
+
+// Don't call this with a non-class. HasSerializeFunction::value is true if the
+// type T has a static or non-static Serialize() function.
+template<typename T>
+struct HasSerializeFunction
+{
+ static const bool value =
+ // Non-static version.
+ HasSerializeCheck<T, void(T::*)(boost::archive::xml_oarchive&,
+ const unsigned int)>::value ||
+ // Static version.
+ HasSerializeCheck<T, void(*)(boost::archive::xml_oarchive&,
+ const unsigned int)>::value;
+};
+
+template<typename T>
+struct HasSerialize
+{
+ // We have to handle the case where T isn't a class...
+ typedef char yes[1];
+ typedef char no [2];
+ template<typename U, typename V, typename W> struct check;
+ template<typename U> static yes& chk( // This matches classes.
+ check<U,
+ typename boost::enable_if<boost::is_class<U>>::type*,
+ typename boost::enable_if<HasSerializeFunction<U>>::type*>*);
+ template<typename > static no& chk(...); // This matches non-classes.
+
+ static const bool value = (sizeof(chk<T>(0)) == sizeof(yes));
+};
// Declare the shims we need.
template<typename T> class FirstShim;
@@ -58,10 +88,7 @@ template<typename T>
inline FirstShim<T> CreateNVP(
T& t,
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)
+ typename boost::enable_if<HasSerialize<T>>::type* = 0)
{
return FirstShim<T>(t, name);
}
@@ -82,7 +109,7 @@ inline FirstShim<T> CreateNVP(
* Note that the second parameter, 'name', must be a valid XML identifier.
*
* This particular overload is used by classes that do not have a Serialize()
- * function (so, no shim is necessary).
+ * function (so, no shim is necessary) or primitive types that aren't pointers.
*
* @param t Object to create NVP (name-value pair) with.
* @param name Name of object (must be a valid XML identifier).
@@ -95,43 +122,7 @@ const // Imitate the boost::serialization make_nvp() function.
boost::serialization::nvp<T> CreateNVP(
T& t,
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 boost::serialization::make_nvp(name.c_str(), t);
-}
-
-/**
- * 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. The template type should be automatically
- * deduced, and the two boost::enable_if<> parameters are automatically deduced
- * too. So usage looks like
- *
- * @code
- * MyType t;
- * CreateNVP(t, "my_name_for_t");
- * @endcode
- *
- * Note that the second parameter, 'name', must be a valid XML identifier.
- *
- * This particular overload is used by primitive types that aren't pointers.
- *
- * @param t Object to create NVP (name-value pair) with.
- * @param name Name of object (must be a valid XML identifier).
- */
-template<typename T>
-inline
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-const // Imitate the boost::serialization make_nvp() function.
-#endif
-boost::serialization::nvp<T> CreateNVP(
- T& t,
- const std::string& name,
- typename boost::disable_if<boost::is_class<T>>::type* = 0,
+ typename boost::disable_if<HasSerialize<T>>::type* = 0,
typename boost::disable_if<boost::is_pointer<T>>::type* = 0)
{
return boost::serialization::make_nvp(name.c_str(), t);
@@ -166,10 +157,7 @@ const
boost::serialization::nvp<PointerShim<T>*> CreateNVP(
T*& t,
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)
+ typename boost::enable_if<HasSerialize<T>>::type* = 0)
{
return boost::serialization::make_nvp(name.c_str(),
reinterpret_cast<PointerShim<T>*&>(t));
@@ -191,43 +179,7 @@ boost::serialization::nvp<PointerShim<T>*> CreateNVP(
* Note that the second parameter, 'name', must be a valid XML identifier.
*
* This particular overload is used by pointers to classes that do not have a
- * Serialize() function.
- *
- * @param t Object to create NVP (name-value pair) with.
- * @param name Name of object (must be a valid XML identifier).
- */
-template<typename T>
-inline
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-const
-#endif
-boost::serialization::nvp<T*> CreateNVP(
- T*& t,
- 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 boost::serialization::make_nvp(name.c_str(), t);
-}
-
-/**
- * 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. The template type should be automatically
- * deduced, and the two boost::enable_if<> parameters are automatically deduced
- * too. So usage looks like
- *
- * @code
- * MyType t;
- * CreateNVP(t, "my_name_for_t");
- * @endcode
- *
- * Note that the second parameter, 'name', must be a valid XML identifier.
- *
- * This particular overload is used by pointers to non-classes.
+ * Serialize() function, or pointers to non-classes.
*
* @param t Object to create NVP (name-value pair) with.
* @param name Name of object (must be a valid XML identifier).
@@ -240,7 +192,7 @@ const
boost::serialization::nvp<T*> CreateNVP(
T*& t,
const std::string& name,
- typename boost::disable_if<boost::is_class<T>>::type* = 0)
+ typename boost::disable_if<HasSerialize<T>>::type* = 0)
{
return boost::serialization::make_nvp(name.c_str(), t);
}
@@ -257,10 +209,7 @@ 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)
+ typename boost::enable_if<HasSerialize<T>>::type* = 0)
{
return FirstArrayShim<T>(t, len, name);
}
@@ -270,33 +219,14 @@ inline FirstArrayShim<T> CreateArrayNVP(
* 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.
+ * Serialize() function or 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)
+ typename boost::disable_if<HasSerialize<T>>::type* = 0)
{
return FirstNormalArrayShim<T>(t, len, name);
}
More information about the mlpack-git
mailing list