Boost logo

Boost Users :

From: Robert Ramey (ramey_at_[hidden])
Date: 2005-02-19 21:17:01


> Currently, the save/load methods inspect the Base object's creation
> key. If the key is blank, the object is serialized directly (a test
> class). If the key is not blank, the creation key is serialized
> (thus, a "production" class). Before this is done, a boolean flag is
> serialized indicating that a creation key was used to store the object
> or the object itself was stored. This is it, in rough form:
>
> template <class Archive>
> void save(Archive& ar, unsigned int) const {
> bool flag = key.size() != 0;
>
> ar << flag;
>
> if (flag) {
> ar << my_base->key();
> } else {
> ar << my_base;
> }
> }
>
> template <class Archive>
> void load(Archive& ar, unsigned int) {
> bool flag;
>
> ar >> flag;
>
> if (flag) {
> string key;
> ar >> key;
> my_base = Factory::create(key);
> } else {
> ar >> my_base;
> }
> }
>
> Now, this works just fine, but it is a bit inelegant (a friend calls
> this uninheritance).

This pretty much replicates what the serialization system does when
serializing class marked with BOOST_CLASS_EXPORT

> I would prefer to be able to encapsulate the logic of serialization
> in a separate class, something like this:
>
> class BaseHandle {
> Base* my_base;
>
> template <class Archive>
> void save(Archive& ar, unsigned int) const {
> // As above.
> }
>
> template <class Archive>
> void load(Archive& ar, unsigned int) {
> // As above.
> }
>
> };
>
> Then, the Thing class, and any other class that would want
> to serialize a Base object would be straightforward:
>
> class Thing {
> Base* my_base;
>
> template <class Archive>
> void save(Archive& ar, unsigned int) const {
> ar << my_base;
> }
>
> template <class Archive>
> void load(Archive& ar, unsigned int) {
> ar >> my_base;
> }
> };
>

The above is supported exactly as written by the serialization library

> My question is: Has anyone else run across this type of pattern? I
> would prefer to use a shared pointer to the Base class throughout and
> to hide the constructors of all Base (and its derived classes), to
> force allocation of these objects through special static alloc methods
> that create shared_ptr-wrapped objects.
>
> My problem is I don't quite know how to combine all of these ideas.
>
> For example, using shared_ptr, class Thing would be quite simple:
>
> typedef shared_ptr<Base> BasePtr;
>
> class Thing {
> BasePtr my_base;
>
> template <class Archive>
> void save(Archive& ar, unsigned int) const {
> ar << my_base;
> }
>
> template <class Archive>
> void load(Archive& ar, unsigned int) {
> ar >> my_base;
> }
> };

The above is also supported exactly as written by the serialization library.
Its in the documentation. The explanation particular to shared_ptr<T> is in
the case study - shared_ptr;

> However, now I've broken the previous work: I'd have to go back and
> put all of the serialization logic for factory construction back
> in the Thing class itself.

Hmmm - I far as I can see it was redundant in the first place.

>
> If I try to combine all of this in the BaseHandle class, I run into
> difficulties:
>
...

The above is what you want. In fact I would make it even simpler in this
particular case:

       class Thing {
         shared_ptr<Base> my_base;

         template <class Archive>
         void serialize(Archive& ar, unsigned int) const {
             ar & my_base;
         }

     };

      BOOST_SHARED_POINTER_EXPORT(DerivedProductionA)
      BOOST_SHARED_POINTER_EXPORT(DerivedProductionB)
     ... // other classes derived from Base

I think that would be all that is necessary.

Robert Ramey


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net