Hello,
While using the latest release of boost, I've encountered a few questions concerning the usage of the serialization library with objects without default constructors.
Here they are:
1-) How can we construct an instance of a serialized object that doesn't have a default constructor?
The only option I've figured out is to normally construct an object with bogus values, then unserialize the real values while reading from the archive. Example:
X(0) val; // 0 being some bogus value.
inputStream >> val; // Overwrites all values within val;
Is this the correct way to do things?
No.. But I think what you want can be found in the manual in section: If you specialize save/load construct data you will get what you want. Use construct in place inside of load construct data.
Reference/Serializable/Concept/Pointers/Non-Default Constructors.2-) How should we split the serialization between the class' serialize member versus load/save_construct_data?
My observations show that when un/serializing objects directly like shown above, load/save_construct_data aren't needed, so the serialize member has to handle everything. When serializing a vector<X>, load/save_construct_data does get called, so we have to un/serialize some members in those functions as well. At first glance, it seems some members will have to be un/serialized for the second time within load/save_construct_data.
Is that correct? For a class to be correctly un/serializable for all cases, load/save_construct_data must un/serialize members that are already taken care of in the serialize member?
Nope.
If his isn't simple, then there is something wrong. Check the code in test_non_default_ctor . If it still doesn't give you what you need, ask again.
RObert Ramey
OK I see the problem now.Let me re-state it to be sure we're on the same page.The class Person has a const member _name. In C++ const members can only be set when an object is constructed. In order to make sure no object is created without a name, There is no default constructor. When the serialization library creates a new instance - that is when loading a pointer, the library uses the non-default constructor to initialize the const variable with the correct value. When restoring the contents of an instance of the class Person that already exists the const member is not set.Which seems totally correct to me.
The real question here is what is the intent in setting the member variable _name as const? Standard C++ behavior for const members is that theya) are only set when the instance is constructed.b) cannot be changed thereafter.Now if we do the following:Person p("bob")...ar << p;...Person p1("anne");...ar >> p1;What should p1 contain? If you want p1 to contain "anne", then leave your program as it is. If you want it to contain "bob" then:a) remove the const from the member _nameb) implement the normal member serialization for _name.c) at this point, loading pointers will result in _name being loaded twice. If this is a problem, you couldi) add a default constructor and elminate the save/load construct data. You might want to make the default constructor private and include friend boost::serialization::access to your class. (I haven't tried this but I believe it should work.An alternative to a) above would be to leave the "const" but use a const_cast inside the class serialization function.At the heart of the matter here is the what we want const to mean. Should const variables never change during the life of the class? - then we expect p1 to contain "bob". Otherwise they are not really "const" in the traditional C++ sense and should be addressed by removing the const, or a cast or?
what I really mean is what is the matter with
class A {const X m_x...template<class Archive>void serialize(Archive & ar, const unsigned int version){ar >> const_cast<X>(m_x);}};
Doesn't this give the same result in a simpler more transparent way?
Robert Ramey