Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2003-10-01 11:53:23


Personally I refrain from the creation of gratuitous default
constructors. see Scott Meyers, More Effective C++, item 4
pages 19-24. C++ syntax rules and the current serialization
implementation for vectors help me from accidently
contravening this practice. When I get a compile error I
review the design and decide to change my design or
override the above practice ( in my case I always change
my design). Under the current system I have several
options

a) change my design - which is what I try do
b) add a public default constructor
c) add a private default constructor and give collection
serialization to it by adding in a friend
d) alter the serialization implementation for a different one

The proposal to grant private access to all serialization
functions is a bad idea for the same reason that
making the default constructor public is a bad idea. It
gives access to who knows who in a silent manner.

An example illustrates my concerns:

class X {
        friend boost::serialization::access ;
private:
        X(){};
public:
        const int m_value; // never changes
        X(int i) : mvalue(i)
        template<class Archive>
        void serialize(Archive &ar){}
};

main
        text_archive oa(...)
        vector<X> x_vector;
        X x(24);
        x_vector. push_back(x).
        oa << x_vector;
        ...
        text_archive ia(...)
        vector<X> new_x_vector;
        ia >> new_x_vector;
        // x_vector and new_x_vector are not equal !!!
        // this is OK?
}

With the current system, the above code would be flagged at compile time.
With the proposed changes, the above would compile and link without
problem but probably not produce the expected results.

In general if you want to serialize objects that require constructors with
arguments, special consideration must be given and I don't believe there
is a one-size-fits-all answer. BTW anytime one specifies a non-default
constructor one has to address these considerations.

So that is my argument about required a specific override
rather than making giving a particular serialization (stl collections)
priviledged access to private functions.

Robert Ramey

>Vladimir Prus wrote::

>> How do I know if I should add
>>
>> friend class boost::serialization::stl::access;
>>
>> to a class. Naturally, I have to if I plan the serialize vectors of the
>> class. It's possible to add this to every class, but then it's just extra
>> typing. If I don't add it by default, then I'll have to add it the first
>> time I'm going to serialize a vector of class. So the system becames
>> unstable: some C++ module suddenly decides to serialize a vector of my
>> class, and I have to change declarations in header.

>If I got it right, Robert is reluctant to have deserialization require
>default-constructability, even private, since it is different things.

Current system requires default constructable. I'm reluctant to override
C++ rules that inhibit automatic creation of a default constructor if
if a specific constructor has already been provided.

>Obviously, for a user to make her class serializable by adding a simple
>serialize member function, the serialization lib must be able to construct
>an object, only to call this function on. (I'll call that a pre-object, for
>clarity)

If there is no constructor specifed - C++ creates a default one. Vladimirs
problem with this is that's public.

>Banning the ability to construct a pre-object just so to avoid defining a
>misleading default-constructor is a pity, as it imples defining less
>concise out-of-class de-serialization functions.

I'm not banning it - I'm just required that it be either public, or that
special access be explicitly granted.

Dave Abrahams wrote:
> If I got it right, Robert is reluctant to have deserialization require
> default-constructability, even private

seiralization of collections requires default constructability accessible
to the functions delcared in the header that implements collection
serialization. The C++ default constructor is fine (as its public).
Making it private - er makes it private. What is proposed is that
the implementation be tweaked so that private doesn't mean
what it normally does but rather private accept for the functions
defined in collection_imp.hpp

>I certainly agree that it's a nasty constraint. I think I can see
>only one way to achieve non-intrusive deserialization in portable C++:
>the deserialization function gets an address into which the object
>will be constructed with placement new. The main downside of this
>approach is that it becomes difficult to deserialize subobjects.

The truth is that I totally overlooked the possibility of using
placement new. The repercussions of this have to my knowledge
been completly unexplores.

Robert Ramey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk