Boost logo

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