Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2005-11-28 00:11:20


Peter Dimov wrote:
> Robert Ramey wrote:
>> Peter Dimov wrote:
>>
>>> When the author of X that has two fields x and y wants to serialize
>>> it into _any_ archive, he just "says" save(x) and save(y) to the
>>> archive.
>>>
>>> However, the author of Y that contains an array currently can't just
>>> say save_array(a) to the archive, because save_array is not part of
>>> the current vocabulary. He needs to say save(a[0]), save(a[1]), ...,
>>> save(a[n-1]).
>>
>> he needs to say save(a) that is ar << a. In any of the proposals
>> the correct override will be invoked.
>
> This only works for C-style arrays with the size fixed at compile
> time.
> Think about how one would write "save" for the following:
>
> template<class T> struct my_array
> {
> T * data_;
> unsigned size_;
> };

OK - I depended on the [] indicating C++ arrays

Take a look at the "Serialization Wrapper" concept as described in the
manual. (The explanation is a little messed up but I'll fx that later).
The
basic idea is to define

template<class T>
struct nvp : public pair<const char *, T*>
{
   ....
    // default implementation of serialize
    template<class Archive>
    void serialize(Archive &ar, const unsigned int){
        // default implemention just throws away the tag name
        // and serializes the value
        ar & t;
    }
    ....
};

text and binary archives don't have to do anything special regarding nvp -
they just
hand it off the serialization library as they do for anyother type. No
save(nvp ... appears
in any header other than in xml_archive. So the default serialization gets
invoked
for those archives.

In xml_archives, there are save/load_override functions like the following.

// special treatment for name-value pairs.
template<class T>
void save_override(
    const
   ::boost::serialization::nvp<T> & t,
    int
){
   this->This()->save_start(t.name());
   archive::save(* this->This(), t.const_value());
   this->This()->save_end(t.name());
}

This implements special behavior for the nvp type when used with the
xml_archive.

I invented this so I wouldn't have some special functions for xml having to
be defined
for all archives. It bothered me that binary_archive would have to "be
aware" or
implement anything related to xml.

I think the same would work for arrays.

define an array wrapper something like:

template<class T>
struct array
{
    std::size_t & m_element_count;
    T & * m_t;
    explicit array(std::size &s, T & t) :
        m_element_count(s),
        m_t(t)
    {}
    // default implementation
    template<class Archive>
    void serialize(Archive &ar, const unsigned int){
        // default implemention does the loop
        std::size count = m_element_count;
       T * t = m_t;
        while(0 < count--){
            ar << *t;
    }
}

hpc_oarchive and/or its derivatives would contain something like the
following.

template<class T>
void save_override(
    const
   ::boost::serialization::array<T> & t,
    int
){
   this->This()->save_array(t.m_element_count, t.m_t)[
}

Note this require refinement to deal with composition with other
wrappers, compiler quirks, and things like that. I hope this doesn't
obscure the main point.

So the net effect is

Everyone who want's to wrap his "arrays" in boost::serialization::array is
free to do
so. Archive classes which don't have special code for such arrays just pass
it to
the library by default which eventually resolves to an item by item
serialization.

Archives which have facilities suitable for handling arrays in a special way
can overload save_override(boost::serialization::array ... and do thier
thing.

No currently existing archives need be changed.

Archives which don't have special handling for these "array" (the majority)
can
completely ignore this facility. These will work exactly as before.

It would mean that our current implementation of std::vector and C++ arrays
would have to be altered to wrap the "arrays" but I could live with that. I
already
bit that bullet with nvp's. The main thing is that it avoids the that which
I was
most unhappy with - having to add something to all archive classes just to
accomodate some special feature of one of them.

Finally, it defines the "array-ness" of a data structure independantly of
the the
whole archive concept. That its "array-ness" becomes an optional feature
of the data. This seems more "correct" to me. It certainly more in
keeping
with the spirt and design of the library to date.

Robert Ramey


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