Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-10-05 14:14:54


brangdon_at_[hidden] (Dave Harris) writes:

> In-Reply-To: <01C389BC.BF188CE0_at_[hidden]>
> ramey_at_[hidden] (Robert Ramey) wrote (abridged):
>> Here is a slightly longer explantation:
>>
>> case I Serialization objects already created - the most common case
>>
>> Objects already exist no creation necessary. serialization saves
>> and reloads their current state.
>>
>> case II Serialization of pointers
>>
>> Objects must be created. Default non-intrusive load uses a default
>> constructor ( which may be private). If an application requires
>> a non - default constructor a non - default load and save must
>> be specified. Usually this will
>>
>> a) save construction parameters before saving the object.
>> b) load the saved construction parameters before creating the object.
>> At the time of object creation the construction parameters are
>> available so all is well.
>
> I think part of the issue is how the memory is managed. As I understand
> it, currently the library combines memory allocation with construction in
> both cases. The first case has a user-function like:
>
> template<class Archive, class T>
> void load(Archive & ar, T & t, unsigned int version);
>
> where t is already allocated and constructed before the function is
> called. The second case has a user-function like:
>
> template<class Archive ar, class T>
> void load(Archive & ar, T * &t, unsigned int file_version);
>
> which is responsible for both allocation and construction and loading.
>
> Did you consider separating out allocation in this second case?
> Specifically, adding an function which just does construction and loading,
> with a default implementation like:
>
> template<class Archive, class T>
> void load_construct(Archive & ar, T *pt, unsigned int version)
                                       ^^^
You'd better make that a void*. Copying a T* which points to memory
that doesn't contain a T causes undefined behavior IIRC.

> {
> new( pt ) T(); // Default-construct in place.
> load( ar, *pt, version ); // Call load for constructed object.
> }
>
> Then the pointer version of load could be rewritten something like:
>
> template<class Archive ar, class T>
> void load(Archive & ar, T * &t, unsigned int file_version)
> {
> char *p = NULL;
> try{
> p = new char[sizeof(T)];
> t = reinterpret_cast<T*>(p);

It also makes the cast go away, and removes an opportunity for
implementation-defined behavior.

> load_construct( ar, t, file_version );
> }
> catch(...){
> delete p;
> throw;
> }
> }
>

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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