Boost logo

Boost Users :

Subject: [Boost-users] [Serialization] good practice for serialization with private default constructors
From: David Rajaratnam (daver_at_[hidden])
Date: 2014-04-03 21:20:26


I am interested to know what is good practice when dealing with
serializable classes with private default constructors. In particular it
is not clear what is the cleanest way to deserializing these objects.

Explaining with reference to the example from:

http://stackoverflow.com/questions/7123613/boost-serialization-does-the-default-constructor-have-to-be-public

The answer to this stackoverflow question shows how to
serialize/deserialize an object with a private default constructor.
Summarizing:

   class Colour {
       friend class boost::serialization::access;
       // private default constructor
       // template serialize function
   public:
      boost::shared_ptr<Colour> test() { // returns new object; }
   };

    int main(){
       boost::shared_ptr<Colour> c = Colour::test();
       std::stringstream str;
       boost::archive::text_oarchive oa(str);
       oa & c;
       // ...
       c.reset();
       boost::archive::text_iarchive ia(str);
       ia & c;
   }

However, it is important to observe that it is not just
serializing/deserializing the object itself but also the shared pointer
to the object! So for example: replacing "ao & c;" with "oa & *c;" will
compile and properly serialize (only) the object, but will throw an
exception when it tries to deserialize because it is expecting a shared
pointer to the object.

My solution to this is to provide a constructor that takes an archive
object:

   class Colour
   {
        // other stuff
    public:
        template<typename Archive>
        Colour(Archive& ar)
       {
            ar >> *this;
       }
   };
   // some explicit specializations where there are
   // other single argument constructors

The example main then becomes:
 
    int main(){
       boost::shared_ptr<Colour> c = Colour::test();
       std::stringstream str;
       boost::archive::text_oarchive oa(str);
      oa & *c;
      // ...

      boost::archive::text_iarchive ia(str);
      Colour c2(ia);
   }

The above works and is clean in that only the Colour object is being
serialized/deserialized. However, I'm not sure if it is good practice.
In particular:

- I presume there will be an intermediate copy of the Colour object
being created by the archive object.
- Passing *this to a function that takes an object of type Object from
within the constructor seems like a bad thing.
- In general template based constructors seems like they should be avoided.

So, my question is whether my solution is reasonable or is there a
better option.

Regards,
Dave R.


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