Commit 96eecf4b authored by Joseph Mirabel's avatar Joseph Mirabel
Browse files

Add free-function serialization macro

parent e5d026e4
......@@ -20,6 +20,7 @@
#define HPP_UTIL_SERIALIZATION_FWD_HH
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/split_free.hpp>
namespace boost {
namespace serialization {
......@@ -37,9 +38,9 @@ class access;
void serialize(Archive & ar, const unsigned int version)
/// Macro that should be put in a serializable class
/// It declare a \c load and \c save function.
/// \note for the load function, an empty constructor (that can leave the object
/// unitialized) must exist.
/// It declares functions \c serialize, \c load and \c save. The two last
/// must be implemented by the caller.
/// \note an empty constructor (that can leave the object unitialized) must exist.
#define HPP_SERIALIZABLE_SPLIT() \
BOOST_SERIALIZATION_SPLIT_MEMBER() \
friend class boost::serialization::access; \
......@@ -50,4 +51,23 @@ class access;
template<class Archive> \
void load(Archive & ar, const unsigned int version)
/// Macro that should be put in a serializable class, using a free function
/// It declares free function \c serialize.
/// This macro must be called outside of any namespace.
/// \note an empty constructor (that can leave the object unitialized) must exist.
#define HPP_SERIALIZABLE_FREE(type) \
namespace boost { namespace serialization { \
template<class Archive> \
void serialize(Archive & ar, type& t, const unsigned int version); \
}}
/// Macro that should be put in a serializable class, using a free function
/// It declares free functions \c serialize, \c load and \c save. The two last
/// must be implemented by the caller.
/// This macro must be called outside of any namespace.
/// \note an empty constructor (that can leave the object unitialized) must exist.
#define HPP_SERIALIZABLE_SPLIT_FREE(type) \
HPP_SERIALIZABLE_FREE(type)
#endif // HPP_UTIL_SERIALIZATION_FWD_HH
......@@ -28,29 +28,59 @@
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/nvp.hpp>
#define _HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,archive) \
template void type::load<archive##_iarchive>(archive##_iarchive& ar, const unsigned int ver); \
template void type::save<archive##_oarchive>(archive##_oarchive& ar, const unsigned int ver) const
#define _HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,archive,arg) \
template void type load<archive##_iarchive>(archive##_iarchive& ar, \
arg BOOST_PP_COMMA_IF(BOOST_PP_NOT(BOOST_PP_IS_EMPTY(arg))) \
const unsigned int ver); \
template void type save<archive##_oarchive>(archive##_oarchive& ar, \
BOOST_PP_IF(BOOST_PP_IS_EMPTY(arg),,const) arg BOOST_PP_COMMA_IF(BOOST_PP_NOT(BOOST_PP_IS_EMPTY(arg))) \
const unsigned int ver) BOOST_PP_IF(BOOST_PP_IS_EMPTY(arg),const,)
#define _HPP_SERIALIZATION_IMPLEMENT(type,archive) \
template void type::serialize<archive##_iarchive>(archive##_iarchive& ar, const unsigned int ver);\
template void type::serialize<archive##_oarchive>(archive##_oarchive& ar, const unsigned int ver)\
#define _HPP_SERIALIZATION_IMPLEMENT(type,archive,arg) \
template void type serialize<archive##_iarchive>(archive##_iarchive& ar, \
arg BOOST_PP_COMMA_IF(BOOST_PP_NOT(BOOST_PP_IS_EMPTY(arg))) \
const unsigned int ver); \
template void type serialize<archive##_oarchive>(archive##_oarchive& ar, \
arg BOOST_PP_COMMA_IF(BOOST_PP_NOT(BOOST_PP_IS_EMPTY(arg))) \
const unsigned int ver)
#define HPP_SERIALIZATION_SPLIT_IMPLEMENT(type) \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,boost::archive::polymorphic); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,boost::archive::xml); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,boost::archive::text); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type,boost::archive::binary)
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type::,boost::archive::polymorphic,); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type::,boost::archive::xml,); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type::,boost::archive::text,); \
_HPP_SERIALIZATION_SPLIT_IMPLEMENT(type::,boost::archive::binary,)
#define HPP_SERIALIZATION_IMPLEMENT(type) \
_HPP_SERIALIZATION_IMPLEMENT(type,boost::archive::polymorphic); \
_HPP_SERIALIZATION_IMPLEMENT(type,boost::archive::xml); \
_HPP_SERIALIZATION_IMPLEMENT(type,boost::archive::text); \
_HPP_SERIALIZATION_IMPLEMENT(type,boost::archive::binary)
_HPP_SERIALIZATION_IMPLEMENT(type::,boost::archive::polymorphic,); \
_HPP_SERIALIZATION_IMPLEMENT(type::,boost::archive::xml,); \
_HPP_SERIALIZATION_IMPLEMENT(type::,boost::archive::text,); \
_HPP_SERIALIZATION_IMPLEMENT(type::,boost::archive::binary,)
#define HPP_SERIALIZATION_FREE_IMPLEMENT(type) \
namespace boost { namespace serialization { \
_HPP_SERIALIZATION_IMPLEMENT(,archive::polymorphic,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::xml,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::text,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::binary,type& t); \
}}
#define HPP_SERIALIZATION_SPLIT_FREE_IMPLEMENT(type) \
namespace boost { namespace serialization { \
template<class Archive> \
void serialize(Archive & ar, type& t, const unsigned int version) { \
split_free(ar, t, version); \
} \
_HPP_SERIALIZATION_IMPLEMENT(,archive::polymorphic,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::xml,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::text,type& t); \
_HPP_SERIALIZATION_IMPLEMENT(,archive::binary,type& t); \
}}
namespace hpp {
namespace serialization {
......
......@@ -23,26 +23,31 @@
#include <boost/archive/polymorphic_xml_iarchive.hpp>
#include <boost/archive/polymorphic_xml_oarchive.hpp>
int run_test ()
template<typename T>
int run_test_tpl ()
{
std::stringstream ss;
Foo foo(10);
Bar bar(20);
T t(10);
{
boost::archive::polymorphic_xml_oarchive oa(ss);
oa << boost::serialization::make_nvp("foo", foo);
oa << boost::serialization::make_nvp("bar", bar);
oa << boost::serialization::make_nvp("t", t);
}
Foo* foo_r = NULL;
Bar* bar_r = NULL;
Foo* t_r = NULL;
{
boost::archive::polymorphic_xml_iarchive ia(ss);
ia >> boost::serialization::make_nvp("foo", foo_r);
ia >> boost::serialization::make_nvp("bar", bar_r);
ia >> boost::serialization::make_nvp("t", t_r);
}
if (foo_r == NULL || foo_r->i_ != foo.i_) return TEST_FAILED;
if (bar_r == NULL || bar_r->i_ != bar.i_) return TEST_FAILED;
if (t_r == NULL || t_r->i_ != t.i_) return TEST_FAILED;
return TEST_SUCCEED;
}
int run_test ()
{
if (run_test_tpl<Foo >() == TEST_FAILED) return TEST_FAILED;
if (run_test_tpl<Bar >() == TEST_FAILED) return TEST_FAILED;
if (run_test_tpl<FooFree>() == TEST_FAILED) return TEST_FAILED;
if (run_test_tpl<BarFree>() == TEST_FAILED) return TEST_FAILED;
return TEST_SUCCEED;
}
......
......@@ -46,3 +46,34 @@ void Bar::save(Archive & ar, const unsigned int version) const
}
HPP_SERIALIZATION_SPLIT_IMPLEMENT(Bar);
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive & ar, FooFree& foo, const unsigned int version)
{
(void) version;
ar & hpp::serialization::make_nvp("i", foo.i_);
}
template<class Archive>
void load(Archive & ar, BarFree& bar, const unsigned int version)
{
(void) version;
ar & hpp::serialization::make_nvp("i", bar.i_);
}
template<class Archive>
void save(Archive & ar, const BarFree& bar, const unsigned int version)
{
(void) version;
ar & hpp::serialization::make_nvp("i", bar.i_);
}
}
}
HPP_SERIALIZATION_FREE_IMPLEMENT(FooFree)
HPP_SERIALIZATION_SPLIT_FREE_IMPLEMENT(BarFree)
......@@ -35,3 +35,25 @@ class Bar {
Bar() {}
HPP_SERIALIZABLE_SPLIT();
};
class FooFree {
public:
FooFree(int i) : i_ (i) {};
int i_;
private:
FooFree() {}
};
HPP_SERIALIZABLE_FREE(FooFree)
class BarFree {
public:
BarFree(int i) : i_ (i) {};
int i_;
private:
BarFree() {}
};
HPP_SERIALIZABLE_SPLIT_FREE(BarFree)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment