Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize derived template classes with Boost.serialize?

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?

like image 610
Anton Kazennikov Avatar asked Aug 26 '09 05:08

Anton Kazennikov


1 Answers

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.

like image 182
Arpegius Avatar answered Nov 07 '22 19:11

Arpegius