|
Boost : |
From: Vladimir Prus (ghost_at_[hidden])
Date: 2003-10-06 00:42:08
Dave Harris wrote:
>> I don't think it adds anything to the system
>
> Well, it solves various problems that have been discussed recently. It
> avoids needing a default constructor and/or friend. This is important if
> we're to serialise vectors of T without being intrusive. Supporting
> std::vector, and not requiring code modifications to serialised classes,
> are two of the design goals (6 and 9).
As Robert noted, you still have to make load_construct a friend of the
serialized class. Yes, you can add the "friend" declaration, but if my
class C is serializable I want vector<C> to be serializable, always. So,
for a lots of clases, I'd have to befriend 'load_construct'. Not nice ---
I've already given serialization lib access to private sections.
> Also, it is simpler to use because load_construct doesn't need to allocate
> memory, get the try/catch block right, etc. To me it just seems like the
> right separation of concerns.
It's hard to tell definitely, but I believe customizing load/save should be
very rare, so this should not matter too much.
>> and makes it harder to understand and explain. Of course that's a
>> subjective assesment so I can't defend it on technical grounds.
>
> Indeed. To me it is a bit simpler. Write load for existing objects, and
> load_construct to control how they are created. Passing void * instead of
> T * makes the different roles even clearer.
>
> Incidently, this provides an idiom for serialising immutable objects -
> write load_construct and not load. I think this could eventually be
> developed into something interesting, although I wouldn't want to hold up
> the library because of it.
Eh... you gave the following example:
template<class Archive>
void load_construct(Archive & ar, my_class *pt, unsigned int version)
{
int a;
ar >> a;
new( pt ) my_class( a );
load( ar, *pt, version );
}
It's good, but it presumes that "save" method has written "a" for you to
load. That's somewhat breaks duality between "save" and "load". Now "save"
should care about another function "load_construct", which is somewhat more
complex.
>> As I said before my personal preference is that objects never have an
>> invalid state. I've found that any thing that uses STL sometimes copies
>> things without my being aware of it so its the only way I can have
>> confidence that i don't have another obscure bug to find. Havng said
>> that, don't think that its a good idea for a serialization package to
>> enforce this point of view.
>
> If people want to make the default implementation of load_construct a
> friend, so it can use the default constructor, they can do that. Nothing
> is being ruled out. However, it does grant some more flexibility.
>
>
>> the load_construct would still have to gain access to a private default
>> constructor so I don't see that it addresses the original concern
>> raised by Vladimir.
>
> On the contrary, the point is that load_construct can be overridden by the
> user not to use a default constructor. I gave this example:
>
> template<class Archive>
> void load_construct(Archive & ar, my_class *pt, unsigned int version)
> {
> int a;
> ar >> a;
> new( pt ) my_class( a );
> load( ar, *pt, version );
> }
>
> Load_construct uses a constructor which takes an int, which presumably is
> already public. So this lets us serialise my_class without needing to add
> a public default constructor, or a private default constructor and
> "friend", either of which would mean editing the class's definition.
FWIW, in my use case it won't work, since I don't have any ctor which can be
used to reconstruct the class instance given field values.
- Volodya
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk