Boost logo

Boost :

From: Dave Harris (brangdon_at_[hidden])
Date: 2003-10-13 08:18:00


In-Reply-To: <01C39102.7246A3A0_at_[hidden]>
ramey_at_[hidden] (Robert Ramey) wrote (abridged):
> But - . In the current system - collection loading will have to be
> overridden for each T as well.
>
> So, at long last, I believe I see the motivation of factoring out
> "load-construct" so that for classes without a default constructor
> we don't have to override in two places. I will consider this some
> more.

OK. And I'll return the favour by looking at what is possible using your
approach.

I now think the difference is merely one of efficiency. With your API we
can load a vector with something like:

     template <typename Archive, typename Collection, typename T>
     void load_collection( Archive &ar, Collection &c,
             unsigned int version ) {
         c.clear();
         typename Collection::size_t size;
         ar >> size;
         if (size == 0)
             return; // All done.
             
         std::auto_ptr<T> pt;
         ar >> pt; // Uses pointer load.
         c.push_back( *pt );
        
         for (--size; size != 0; --size) {
             ar >> *pt;
             c.push_back( *pt );
         }
     }

Not real code - I have omitted reserve(), XML etc. The idea is to create
the T on the heap. This will make use of the pointer version of load(),
and if the user has overloaded that not to need a default constructor,
everything will be fine.

By treating the first item as a special case, we need 1 heap allocation
rather than N. This may be affordable. As you've said elsewhere, the big
efficiency cost may be the copying implied by push_back. In order to do
substantially better, I think we need (a) access to the vector's
uninitialised memory; and (b) a way to load items directly into that
memory. Then we can avoid all copying. However, as far as the STL is
concerned only the implementor gets (a). Until that is resolved (b) is
moot. Meanwhile the above approach may be good enough.

However, it would be a shame to have to use this for types which did have
an available default constructor. I am not current on C++ template idioms
- is there a way to detect default constructors? If so perhaps the library
could switch automatically between your fast implementation and the above
general one. Maybe it is worth adding something to the class serialisation
traits.

By the way, I've assumed auto_ptr can be serialised. If not, use something
like:

         T *temp_pt;
         ar >> temp_pt;
         std::auto_ptr<T> pt(temp_pt);

to load into a normal pointer and then transfer to auto_ptr for exception
safety.

Also, I've not given code for save_collecton but it probably needs to be
changed in line with load_collection, to treat the first item in the
container specially.

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