Boost logo

Boost Users :

Subject: [Boost-users] [Serialization] serialize from and to an already instantiated object.
From: nico (nicolas.guillot_at_[hidden])
Date: 2011-05-22 15:07:24


Hello.

I use boost.serialization to perform save and load to files.
If a class is serializable through the boost mechanism, I'd like to easily
add the "savable" feature (through serialization and boost archives).

Here how I do, and then I've got 2 questions.
I don't post all the #include statements.

Let's have a serializable class (I only use text archive for this example)

---------MyClass.h---------

class MyClass
{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

    int data_;

public:
    MyClass();
    virtual ~MyClass();
};

BOOST_CLASS_EXPORT_KEY(MyClass)

---------MyClass.cpp---------

MyClass::MyClass() : data_(123) {}
MyClass::~MyClass() {}

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

// instanciate the serialize function for text archives
#include "boost/archive/text_iarchive.hpp"
#include "boost/archive/text_oarchive.hpp"
template void MyClass::serialize(boost::archive::text_iarchive & ar, const
unsigned int version);
template void MyClass::serialize(boost::archive::text_oarchive & ar, const
unsigned int version);
BOOST_CLASS_EXPORT_IMPLEMENT(MyClass)

---------

Now I define a FileSavable class. Its purpose is to add the "save-to-file"
feature to a class that can be serialized in a text archive, making the
latter inherting from FileSavable, and adding a line in its serialize
function, I write it below).

---------FileSavable.h---------

class FileSavable
{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

public:
    virtual ~FileSavable() {}
    void SaveToFile(std::string path);
    void LoadFromFile(std::string path);
};

BOOST_CLASS_EXPORT_KEY(FileSavable)

---------FileSavable.cpp---------

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

void FileSavable::SaveToFile(std::string path)
{
    std::ofstream ofs(path.c_str());
    assert(ofs.good());
    boost::archive::text_oarchive oa(ofs);
    oa & this;
}

void FileSavable::LoadFromFile(std::string path)
{
    std::ifstream ifs(path.c_str());
    assert(ifs.good());
    boost::archive::text_iarchive ia(ifs);
    FileSavable* p;
    ia & p;
    *this = *p;
    delete p;
}

// instanciate the serialize function for text archives
 #include "boost/archive/text_iarchive.hpp"
 #include "boost/archive/text_oarchive.hpp"
 template void FileSavable::serialize(boost::archive::text_iarchive & ar,
const unsigned int version);
 template void FileSavable::serialize(boost::archive::text_oarchive & ar,
const unsigned int version);
BOOST_CLASS_EXPORT_IMPLEMENT(FileSavable)

---------Modification to MyClass---------
It now inherit from FileSavable:

class MyClass : public FileSavable

The serialize function call the base class:

template<class Archive>
void MyClass::serialize(Archive & ar, const unsigned int version)
{
    ar & boost::serialization::base_object<FileSavable>(*this);
    ar & data_;
}

---------

Thanks if you read me until here, now my questions:

1) I don't care the FileSavable part of MyClass being serialized, but if I
don't call it with boost::serialization::base_object, I have a runtime
error:
terminate called after throwing an instance of
'boost::archive::archive_exception'
  what(): unregistered void cast 7MyClass<-11FileSavable
Do you see a way to avoid having to add this line in MyClass? Ideally, just
having to inheriting from FileSavable would be great: a simple way to add a
feature.

2) As you can see, my LoadFromFile function first creates a new MyClass
object in p, by de-serializing an archive, and then copies this newly
created object into "*this", and finally deletes the object created by the
archive d-eserialization.
I didn't find a way to avoid this temporary and de-serialize directly in
this.
Moreover, my solution is not exception-safe, but I didn't manage to
de-serialize in a temporary auto_ptr nor boost::shared_ptr.

Thanks in advance for replies.

Nicolas.



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net