In this example, we have a class A that doesn't have a default constructor.
An int is needed by the constructor, which is stored in the i member
variable. load/save_construct_data are used to un/serialize the i member,
while the serialize member is used for all other members.

Looking at this test, I see a couple of behaviors that puzzle me.

-) Saving the 'a' instance in the save() function doesn't end up calling
save_construct_data. This leaves a serialized version of A which lacks the
'i' member. This makes it impossible to fully restore the 'a' instance. It
seems problematic to me that save_construct_data isn't called in this case.

I just re-ran test_non_default_ctor. I ran under the VC 7.1 debugger and
inserted traps inside both save_construct_data and load_construct_data. II
verified that save_construct_data and load_construct_data are being invoked
exactly as they are intended. I see no problem here.

 In my planned usage, I'd like to fully serialize all members, regardless if
the objects are serialized directly or through pointers. I cannot see how
to do this without serializing the members needed to reconstruct the object
in both serialize and save_construct_data, even if some members will end up
serialized twice when an object is stored through a pointer.

If the members are not pointers, the constructor is never called. so the
parameters set by the constructor are not needed. save_load_contruct_data
is only called when its necessary to create a new object.

What's the proper way to serialize all members of a class without a default
constructor so that it gets fully serialized regardless how the objects are
managed?

Exactly as described in the manual and illustrated by the example
test_non_default_ctor.

-) When restoring the 'a' instance within load(), in order to restore it, we
first create another 'a' instance (with a different constructor argument),
then restore the other members within, leaving untouched the 'i' member.
Assuming I'd like to be able to serialize and unserialize completely objects
that do not have a default constructor, I'm wondering how I can fully
restore an object that doesn't have a default constructor.

All you have to do is define save_construct_data and load_construct_data for
all types which don't have a default constructor. The library takes care of
everything else.

I've looked for some other mechanism relying on a copy constructor and
something along the lines of load_construct_data, but I haven't found any.

Somehow I'm thinking you're looking for the wrong thing. I wonder if you're
not underestimating what the library does for you. As I said, you, only
need to define save/load_construct_data for those types which don't have a
default constructor - there is nothing else required to do.

Robert Ramey

Hello,

As this discussion is going, it seems clear that either I'm missing something somewhere or that I'm not being clear enough in exposing  my problems...  I'll directly include a sample of something similar to what I'd like to achieve that doesn't work.  Please take a look at the example, and let me know how you would modify this to make both assert succeed.  If you notice that I've missed some concept in the way the library should be used, please enlighten me!

Thanks,

Martin


#include <cstdlib>
#include <cassert>
#include <sstream>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/string.hpp>

using namespace std;

class Person
{
public:
    Person(const string& name) : _name(name), _favoriteFood("none") {}
   
    const string& getName() const {return _name;}
    const string& getFavoriteFood() const {return _favoriteFood;}
    void setFavoriteFood(const string& favoriteFood) {_favoriteFood = favoriteFood;}

private:
    const string _name;
    string _favoriteFood;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & _favoriteFood;
    }
};

namespace boost {
namespace serialization {

template<class Archive>
inline void save_construct_data(Archive & ar, const Person * person, const unsigned int /* file_version */)
{
    ar << person->getName();
}

template<class Archive>
inline void load_construct_data(Archive & ar, Person * person, const unsigned int /* file_version */)
{
    string name;
    ar >> name;
    ::new(person)Person(name);
}

} // serialization
} // namespace boost

template<class Archive>
void serializePerson(Archive& oa, const Person& someone)
{
    // save_construct_data isn't called when serializing a Person in this fashion.
    // The person's name will not appear in the archive.
    oa << someone;
}

template<class Archive>
Person UnserializePerson(Archive& ia)
{
    // I'm constructing a temporary person, with a bogus name, as it's the only workaround I've come up with.
    // There is no way that unserializing returns an actual object, like I'm needing here.
    Person someone("bogus name");

    // When unserializing in this fashion, load_construct_data isn't called either.
    ia >> someone;

    // The initial person's name is then lost.
    return someone;
}

void main(void)
{
    Person *const Joe = new Person("Joe");
    Person John("John");

    stringstream stringStream;

    boost::archive::text_oarchive oa(stringStream);
    oa << Joe;
    serializePerson(oa, John);

    boost::archive::text_iarchive ia(stringStream);
    Person* restoredPersonPointer;
    ia >> restoredPersonPointer;
    Person restoredPerson(UnserializePerson(ia));

    assert(restoredPersonPointer->getName() == Joe->getName()); // works fine.
    assert(restoredPerson.getName() == John.getName()); // fails.
}



--
signature Tel: (450) 681-1681, #271

OKIOK

Enterprise and e-business security solutions
Solutions de sécurité d'entreprise et d'affaires électronique

Tel. : (450) 681.1681
http://www.okiok.com

This e-mail message (including attachments, if any) is intended for the use of the individual or entity to which it is addressed and may contain information that is privileged, proprietary, confidential and exempt from disclosure. If you are not the intended recipient, you are notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please notify the sender and erase this e-mail message immediately.
 
Le présent message électronique (y compris les pièces qui y sont annexées, le cas échéant) s'adresse au destinataire indiqué et peut contenir des renseignements de caractère privé ou confidentiel. Si vous n'êtes pas le destinataire de ce document, nous vous signalons qu'il est strictement interdit de le diffuser, de le distribuer ou de le reproduire. Si ce message vous a été transmis par erreur, veuillez en informer l'expéditeur et le supprimer immédiatement.