C++ templated factory constructor/de-serialization
- by KRao
Hi,
I was looking at the boost serialization library, and the intrusive way to provide support for serialization is to define a member function with signature (simplifying):
class ToBeSerialized {
public:
//Define this to support serialization
//Notice not virtual function!
template<class Archive>
void serialize(Archive & ar)
{.....}
};
Moreover, one way to support serilization of derived class trough base pointers is to use a macro of the type:
//No mention to the base class(es) from which Derived_class inherits
BOOST_CLASS_EXPORT_GUID(Derived_class, "derived_class")
where Derived_class is some class which is inheriting from a base class, say Base_class. Thanks to this macro, it is possible to serialize classes of type Derived_class through pointers to Base_class correctly.
The question is:
I am used in C++ to write abstract factories implemented through a map from std::string to (pointer to) functions which return objects of the desired type (and eveything is fine thanks to covariant types).
Hover I fail to see how I could use the above non-virtual serialize template member function to properly de-serialize (i.e. construct) an object without knowing its type (but assuming that the type information has been stored by the serializer, say in a string).
What I would like to do (keeping the same nomenclature as above) is something like the following:
XmlArchive xmlArchive; //A type or archive
xmlArchive.open("C:/ser.txt"); //Contains type information for the serialized class
Base_class* basePtr = Factory<Base_class>::create("derived_class",xmlArchive);
with the function on the righ-hand side creating an object on the heap of type Derived_class (via default constructor, this is the part I know how to solve) and calling the serialize function of xmlArchive (here I am stuck!), i.e. do something like:
Base_class* Factory<Base_class>::create("derived_class",xmlArchive)
{
Base_class* basePtr = new Base_class; //OK, doable, usual map string to pointer to function
static_cast<Derived_class*>( basePtr )->serialize( xmlArchive ); //De-serialization, how?????
return basePtr;
}
I am sure this can be done (boost serialize does it but its code is impenetrable! :P), but I fail to figure out how.
The key problem is that the serialize function is a template function. So I cannot have a pointer to a generic templated function.
As the point in writing the templated serialize function is to make the code generic (i.e. not having to re-write the serialize function for different Archivers), it does not make sense then to have to register all the derived classes for all possible archive types, like:
MY_CLASS_REGISTER(Derived_class, XmlArchive);
MY_CLASS_REGISTER(Derived_class, TxtArchive);
...
In fact in my code I relies on overloading to get the correct behaviour:
void serialize( XmlArchive& archive, Derived_class& derived );
void serialize( TxtArchive& archive, Derived_class& derived );
...
The key point to keep in mind is that the archive type is always known, i.e. I am never using runtime polymorphism for the archive class...(again I am using overloading on the archive type).
Any suggestion to help me out?
Thank you very much in advance!
Cheers