I have some classes that look roughly like this:
class Base {
public:
virtual ~Base() {}
...
};
class Derived1 {
OuterState1& outerState;
InnerState1 innerState;
...
template <typename Ar>
void serialize(Ar& ar, const unsigned int /*version*/) {
ar & innerState;
}
public:
Derived1(OuterState1& outerState) : outerState(outerState) {}
...
};
class Derived2 {
OuterState2& outerState;
InnerState2 innerState;
...
template <typename Ar>
void serialize(Ar& ar, const unsigned int /*version*/) {
ar & innerState;
}
public:
Derived1(OuterState2& outerState) : outerState(outerState) {}
...
};
Basically, the classes have a state that depends on the outside environment, and I don't want to serialize it. This state may be different for the different subclasses. I want to serialize this class. A good thing is that boost::serialization handles polymorphic classes well, but it seems to me that not well enough for me. I could find the following ways to serialize these objects, neither which I like:
Use global variables for the outer state. Now either we use these global variables inside the class, or overload
load_construct_data()
and create the objects from this global variable. The problem with this solution is that it requires global variables, which is generally a bad design, and breaks if the program needs to handle more than one such states.Do not use the polymorphic serialization feature of Boost. Instead, save the actual type in an enum, then save the object non-polymorphically. When loading, load the type enum, then in a switch create the object of the appropriate type with the appropriate outer state, then load the object non-polymorphically. The problem with this is that I have to do a lot of manual coding that would automagically be done by Boost, and that it doesn't work if I want to serialize a collection of such objects.
Is there any better, more elegant solution for this problem?
The solution is to save the environment-specific state as a pointer in the class. Then save/load it in the archive before the actual classes, and modify its value. So serialization of the base class looks something like this:
Make serialization of the environment specific object a NOP.
When saving, do it like this:
When loading, load the states, then override them. Suppose
outerState1
andouterState2
are located at the same position as before, and already has the new, desired value.On another note, the code presented in the question is not complete. The base class serialization needs to be done, but that's beside the point now.