|
Boost Users : |
Subject: Re: [Boost-users] Problems using boost serializing and custom constructors
From: Frank Birbacher (bloodymir.crap_at_[hidden])
Date: 2012-03-06 16:44:49
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi!
Am 06.03.12 15:58, schrieb Allan Nielsen:
> std::vector<int> data; std::vector<Bar> elements;
>
> Foo() { // do very time consuming calculation to populate "data"
> and "elements" } };
Consider a change in design: make Foo default constructible and
provide a static factory method to populate data and elements:
struct Foo {
...
Foo() {} // empty members
static Foo createWithData() {
Foo result;
// do very time consuming calculation to
// populate "data" and "elements"
return result; // will move, not copy data in C++11
}
};
The Foo(Archive&) approach will not scale well because I guess proper
serialization of Foo will only be possible through a pointer (which
implies the object will be constructed on the heap on
deserialization.) For serialization through a pointer there is a way
to use a non-default constructor as described here:
http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/serialization.html#constructors
> Here is what I have tried:
>
> struct Foo { struct Bar { std::vector<int> * data;
>
> Bar( ) : data( 0 ) { } Bar( std::vector<int> * d ) : data(d) { }
>
> template<class Archive> void serialize(Archive & ar, const unsigned
> int version) { ar & data; // is this correct?
This looks good with the changes in Foo::serialize.
> } };
>
> std::vector<int> data; std::vector<Bar> elements;
>
> Foo() { std::cerr << "Running default constructor" << std::endl;
> data.push_back(1); data.push_back(2); data.push_back(3);
> data.push_back(4); data.push_back(5); elements.push_back( Bar(
> &data ) ); elements.push_back( Bar( &data ) ); elements.push_back(
> Bar( &data ) ); }
>
> template<class Archive> Foo( Archive & ar ) { ar >> data; // is
> this corrent?
It does not match the save operation: saving a pointer and loading a
reference does not match. This is not correct.
> ar >> elements; }
>
> private: BOOST_SERIALIZATION_SPLIT_MEMBER(); friend class
> boost::serialization::access;
>
> template<class Archive> void save(Archive & ar, const unsigned int
> version) const { const std::vector<int> * data_ptr = &data;
>
> // should data be seriliazed as pointer... // it is used as a
> pointer in Bar ar << data_ptr; ar << elements; } };
My proposal: do not split into load/save, use the following instead:
template<typename Archive>
void serialize(Archive &ar, const unsigned int) {
auto * data_ptr = &data;
ar & data_ptr; // load and save through pointer
if(Archive::is_loading::value) {
data = std::move(*data_ptr); // no-throw
ar.reset_object_address(&data, data_ptr);
delete data_ptr; // not sure here
}
// load elements after reset_object_address()
ar & elements;
}
The alternative is to make data a non-std type, like make a custom
struct of it. Then you could just use ar & data & elements in
combination with boost::serialization::track_always.
http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/special.html#objecttracking
HTH,
Frank
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: keyserver x-hkp://pool.sks-keyservers.net
iEYEARECAAYFAk9WhVEACgkQhAOUmAZhnmpFmACfRD1fVPfgrrkEYZpNlOzbi5VS
2EQAn0dHsN3U3FxV/9Wc0TMe2ESy5fWP
=zdeg
-----END PGP SIGNATURE-----
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net