|
Boost : |
From: Dave Harris (brangdon_at_[hidden])
Date: 2003-10-05 15:55:58
In-Reply-To: <01C38B33.28424310_at_[hidden]>
ramey_at_[hidden] (Robert Ramey) wrote (abridged):
> Looking at it now, (leaving aside the non-portability of reinterpret
> cast)
As David Abrahams says, it is probably better to use void * anyway. My
code was just to convey the basic idea.
> 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).
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.
> 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.
> 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.
> template<class Archive ar,>
> void load(Archive & ar, X * &x, unsigned int file_version)
> {
> char *p = NULL;
> try{
> x = new X(ar);
> }
> catch(...){
> delete p;
> throw;
> }
> }
>
> which would permt the constructor to take the parameters right off the
> top of the archive and avoid any special copying. Someone raised this
> possibility before ( I think it may be you) I sort of dismissed it but
> I believe now that it would be accomodated by the current system by
> means of the above override. It might be of use in certain situations
> where copying the constructor parameters is somehow inconvenient.
I replied to someone else who raised it. At the time I expected there was
some override which would make it work, but I didn't know the library well
enough to say what.
The above is fine, but it doesn't handle the vector case. The standard
library goes to a lot of trouble to define vector such that it does not
need T to be default constructible. I think it is important to carry that
forward to serialisation. (Especially if this library may one day become
part of the standard.)
-- Dave Harris, Nottingham, UK
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk