Serializing non-default-constructible objects with boost

Boost serialization is not trivial for an object that has no default constructor. Consider this:

class Foo
{
public:
	int v1;
	int v2;

	Foo(int v1_) { v1 = v1_; }

	template <typename Archive>
	void serialize(Archive& ar, unsigned int version)
	{
		ar & v1;
		ar & v2;
	}
};

//...
binary_iarchive ar;
Foo foo(0);
ar >> foo;

We only suffer a minor inelegance because of redundantly initializing foo. But what if we need to deserialize a pointer?

shared_ptr<Foo> fooPtr;
binary_iarchive ar;
ar >> fooPtr;

This won’t compile, because the deserialization of fooPtr will more or less amount to this:

fooPtr.reset(new Foo);
ar >> *fooPtr;

But of course the first line can’t compile.

Boost’s own doc proposes a solution by overriding two internal functions. One will write v1 (m_attribute in their example), the other will read it and pass to the constructor. Note that v1 is serialized outside serialize().

The solution uses a little-known syntax: ::new(t) my_class(attribute);. This is an explicit constructor call without allocation, which intuitively would be written as t->my_class(attribute);. It is interesting to note that the latter syntax is allowed for destructors: t->~my_class();

My answer to the problem is more like the first example, where the object is dummy-initialized:

namespace boost
{
	namespace serialization
	{
		template<class Archive>
		void load_construct_data(Archive & /*ar*/,
			Foo* t, const unsigned int /*file_version*/)
		{
			::new(t) Foo(0);
		}
	}
}

This simply explains Boost that the correct way of initializing a new Foo is to pass it zero.

Advertisements

Tags: ,

3 Responses to “Serializing non-default-constructible objects with boost”

  1. Jayen Says:

    In the doc, the proposed solution has save_construct_data access a private member. How does that work?

  2. Lev Says:

    When they wrote “friend class boost::serialization::access;”, maybe they meant to make save_construct_data a friend instead. Anyway, you can do that.

  3. Jayen Says:

    but then i get an ambiguity error:

    /usr/include/boost/serialization/serialization.hpp:148: error: call of overloaded ‘save_construct_data(boost::archive::text_oarchive&, const my_class*&, const boost::serialization::version_type&)’ is ambiguous
    /usr/include/boost/serialization/serialization.hpp:83: note: candidates are: void boost::serialization::save_construct_data(Archive&, const T*, unsigned int) [with Archive = boost::archive::text_oarchive, T = my_class]
    bs.cpp:10: note: void boost::serialization::save_construct_data(Archive&, const my_class*, unsigned int) [with Archive = boost::archive::text_oarchive]
    bs.cpp:29: note: void boost::serialization::save_construct_data(Archive&, const my_class*, unsigned int) [with Archive = boost::archive::text_oarchive]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: