12

I'd like to serialize/unserialize following classes:

class Feature{
...
virtual string str()=0;
};

template<typename T>
class GenericFeature : public Feature{
T value;
...
virtual string str();
};

I read boost.serialize docs and the sayed that you must register classes. I can register them in constructor. But there will be problems with loading, as registration will be dynamic, not static(As I understood, you must register classes prior to serialization/deserialization).

How to save/load these type of classes?

Anton Kazennikov
  • 3,574
  • 5
  • 30
  • 38

1 Answers1

15

First tell boost that Feature is abstract, is not always needed:

BOOST_SERIALIZATION_ASSUME_ABSTRACT(Feature);

The serialization method should look more or less like this:

template<class Archive> 
void Feature::serialize(Archive & ar, const unsigned int version)
{
   ar & BOOST_SERIALIZATION_NVP(some_member);
}


template<typename T,class Archive> 
void GenericFeature<T>::serialize(Archive & ar, const unsigned int version)
{
   ar & boost::serialization::base_object<Feature>(*this);  //serialize base class
   ar & BOOST_SERIALIZATION_NVP(some_other_member);
}

Now the tricky point is to register class in serialize/deserialize:

boost::archive::text_iarchive inputArchive(somesstream);

boost::archive::text_oarchive outputArchive(somesstream);

//something to serialize
Feature* one = new GenericFeature<SomeType1>();
Feature* two = new GenericFeature<SomeType2>();
Feature* three = new GenericFeature<SomeType3>();

//register our class, must be all of posible template specyfication    
outputArchive.template register_type< GenericFeature<SomeType1> >();
outputArchive.template register_type< GenericFeature<SomeType2> >();
outputArchive.template register_type< GenericFeature<SomeType3> >();

// now simply serialize ;-]
outputArchive << one << two << three;

// register class in deserialization
// must be the same template specification as in serialize
// and in the same correct order or i'm get it wrong ;-D   
inputArchive.template register_type< GenericFeature<SomeType1> >();
inputArchive.template register_type< GenericFeature<SomeType2> >();
inputArchive.template register_type< GenericFeature<SomeType3> >();

Feature* another_one;
Feature* another_two;
Feature* another_three;

// and deserialize ;-]
inputArchive >> another_one >> another_two >> another_three;

If you need to hide explicit registering somewhere and make it more automatic, there is idea to make special functor template that register one derived class, create all avaible and put in a single list, that one static method of class Feature would register them all. However the problem will be that you need registration for all version of archive, right now i dont know if polymorphic archive will do the job or not.

Arpegius
  • 5,817
  • 38
  • 53
  • I think there's a bug in line 11 of the first code box. If I'm not mistaken, you should have "ar &" to the left of "boost::serialization::base_object". Nice answer though! – Kyle Simek Nov 18 '10 at 01:21
  • 3
    @lionbest: Shouldn't you use `BOOST_SERIALIZATION_BASE_OBJECT_NVP` instead of `boost::serialization::base_object(*this);` – Cookie Aug 22 '11 at 10:23
  • I think you may want to specify name if you have more then one base class. I do not think this macro is needed here, but sure you may want to have one. – Arpegius Aug 23 '11 at 09:30
  • 1
    @Arpegius Do you have an example of hiding the explicit registration? – David Doria Mar 01 '16 at 22:48
  • @DavidDoria Sorry I don't and I found it problematic as there are many types of archives. There may already be better way. General idea is to have FeutureRegistree interface and template TypedFeutureRegistree with constructor that will add its name and pointer to a singleton of static sorted map. Each class that need to be registered needs a static declaration of TypedFeutureRegistree witch will keep the name and version id. Running each object from sorted map that are less then the serialized version over an archive will ensure that all classes are register in correct order. – Arpegius Mar 03 '16 at 00:57
  • @DavidDoria Here is an example where the boost macros are not needed. Instead you need to register the base_object with each child (as Cookie demonstrates), and register each derived class with Archive::template register_type(); http://stackoverflow.com/questions/17698267/polymorphic-serialization-w-boost/33979605#33979605 – SullX May 10 '16 at 13:08