Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Boost serialization Serializing templated derived classes

i would like to serialize a class with an attribute as a list of pointers on a generic class

This is the parent class from which the generic class derives :

class Base{

    public :

        friend class boost::serialization::access;

        virtual ~Base(){}

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

        virtual string Getid() = 0 ;

};

The generic class :

template<typename T>
class GenericBase : public Base
{
    public:

        friend class boost::serialization::access;

        GenericBase<T>(string id){}
        ~GenericBase(){}

        string id;

        vector<T> data

        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & boost::serialization::base_object<Base>(*this);
            ar & BOOST_SERIALIZATION_NVP( id);
            ar & BOOST_SERIALIZATION_NVP( data);

        }

        string Getid() { return id; }

};

The class i want to serialize

class Use
{
    public:

        friend class boost::serialization::access;

        int Id;

        map<string, Base*> BaseDatas;

        Use();
        ~Use();

};

So, after reading the boost serialization doc (http://www.boost.org/doc/libs/1_43_0/libs/serialization/doc/serialization.html#derivedpointers), i tried this in the serialization code :

main(){

   Use u = Use();

   std::ofstream ofs(filename, ios::binary);

   // save data to archive

   boost::archive::binary_oarchive oa(ofs);

   oa.template register_type<GenericBase<Type1> >();
   oa.template register_type<GenericBase<Type2> >();
   oa.template register_type<GenericBase<Type3> >();

   oa<<u;

}

I got a message,

error: 'template' (as a disambiguator) is only allowed within templates

, so i replaced

oa.template register_type >();

by

oa.register_type();

it worked and i have been able to save in text and in binary (i checked the datas)

for loading now, i just used these lines :

main(){

    Use u;

    std::ifstream ifs(filename, ios::binary);

    // load data

    ia.register_type<GenericBase<Type1> >();

    boost::archive::binary_iarchive ia(ifs);

    ia>>u;

}

it threw me an error :

error: no matching function for call to 'GenericBase::GenericBase()'

someone told me i had to override 2 methods save and load like in this sample http://www.boost.org/doc/libs/1_43_0/libs/serialization/doc/serialization.html#constructors

namespace boost { namespace serialization {
template<class Archive>
inline void save_construct_data(
    Archive & ar, const my_class * t, const unsigned int file_version)
    {
        // save data required to construct instance
        ar << t->m_attribute;
    }

template<class Archive>
inline void load_construct_data(
    Archive & ar, my_class * t, const unsigned int file_version)
    {
        // retrieve data from archive required to construct new instance
        int attribute;
        ar >> attribute;
        // invoke inplace constructor to initialize instance of my_class
       ::new(t)my_class(attribute);
    }
}} // namespace ...

but where do I have to define them ? In declaration of the Use class ? And how do I deal with the member

map<string, Base*> BaseDatas;

?

thanks for your help ;)

like image 271
user408535 Avatar asked Oct 15 '22 02:10

user408535


1 Answers

It is easier to comment if you provide a working (cut-and-paste) example of your failing code, with some dummy data ...

But I try to answer anyway ...

Boost.serialisation is trying to call GenericBases default constructor, but fails since you don't provide it. Boost.serialisation first creates your object (or tries now), THEN reads the file and sets the variables.

You could try declaring a protected default constructor, which boost should have access to through access.

like image 81
kod kristoff Avatar answered Oct 18 '22 07:10

kod kristoff