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.