Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2003-10-05 23:27:04


Dave Harris wrote:

>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.

Robert Ramey wrote:
>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.

The default implementation for deserializing a pointer is:

template<class Archive ar, class T>
void load_construct(Archive & ar, T * t, unsigned int file_version)
{
      new( pt ) T(); // Default-construct in place.
        ar >> *t; // presumably
}

template<class Archive ar, class T>
void load(Archive & ar, T * &t, unsigned int file_version)
{
    // If de-serialization fails due to an exception
    // this will guarantee that delete isn't called on a non-null pointer
    t = NULL;
    try{
       //t = new T();
       //ar >> *t;
       p = static_cast<T *>(new char[sizeof(T)]);
       load_construct(ar, static_cast<T *>vp, file_version)
    }
    catch(...){
        delete t;
        throw;
    }
}

I don't see the improvement. You're still stuck with giving load_construct
access to a private constructor. It jush inserts another layer that doesn't
permit you to do anything you couldn't do before. And is raises some
questions about casting of pointers that have to be addressed. The original
code was tansparently correct and obvious how it might be overriden. I don't
think the same can be said for the proposed revision.

Dave Abrahams wrote:

>It seems like everything would be simpler if the library just provided
>the general case, and allowed the user to use post-deserialization
>assignment in the case where she wants to overwrite an existing
>object. But I may be missing something.

>You can handle all those issues by consistenly having deserialization
>construct the objects it's deserializing.

>>I believe this library fullfills this requirement.

>Maybe so. I'm still not sure.

feel free to propose an and example that cannot be handled by
the library or a reasonably straitforward override.

>> 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.

Hmm that would certainly be news to me. You mean I can't copy a
NULL pointer?

>int f()
>{
> Foo x[3];
> return x[0].value();
>}

>The array in the code snippet above does not always exist. It is
>created when the function is entered and destroyed when it exits.

Hence need not be created/constructed by the serialization system which is
which is what is being discussed.

>Elements can be constructed at will in suitably aligned raw memory,
>and an array will be created.

Serialization of the above created "array" requires no special consideration.
Creation of such an array during the de-serialization process
would also be straitforward and part of the normal intrusive or
non-intrusive de-serialization process. The typical case I had in mind
was

class X
{
        Foo foo[3];
        ...
};

no construction by the serialzation library is required or appropriate in such a case.

Robert Ramey


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