Boost logo

Boost :

Subject: Re: [boost] [Serialization] serialize from and to an alreadyinstantiated object.
From: Robert Ramey (ramey_at_[hidden])
Date: 2011-06-09 15:47:07


nico wrote:
> Hello.
>
> I've already posted this topic in the boost-user mailing list, but no
> reply: maybe this boost list is more active... ?
> Anyway:
>
> 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).

I think this is misguided. Including the serialize functions is
all you need to make the class "saveable". Adding something
besides would be redundent.

>
> 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)

I would not include the above macro unless you know you
expect to serialize though a base class pointer.

> ---------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;
>
> }

If you REALLY want something like this, consider something
like the following:

template<class T>
void FileSave(const std::string & path, const T & t){
    std::ofstream ofs(path.c_str());
    boost::archive::text_oarchive oa(ofs);
    oa << t;
}
...

then you instead of

MyClass t;
FileSave(path, t);

you would say

FileSave(path, t);

And if you REALLY want the first syntax
you could at the above FileSave template as a member
to each serialization class

void FileSave(const std::string & path{
    std::ofstream ofs(path.c_str());
    boost::archive::text_oarchive oa(ofs);
    oa << *this;
}
...

I'm not sure what else to say about this.

Robert Ramey

> // 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.
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk