Sign in to follow this  

boost serialization and polymorphic collection

This topic is 3045 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I tried to construct a minimal program with a vector polymorphically storing a number of objects of different classes, and then use boost serialization to serialize/deserialize it. The problem is, the program below crashes when I don't comment out the two lines marked with "//causes exception". I'm not surprised, because as far as I know there's no way for the serialization framework to properly construct the necessary objects with the right type, because in C++ there's simply no generic way of constructing an object given typeinfo, an id or similar, unless I create my own factory class for this. So, how should scenarios such as the one below be handled in practice? E.g. I have a polymorphic collection of classes allocated on the heap and would like to serialize/deserialize it.
#include <fstream>
#include <vector>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/base_object.hpp>

class Foo {
public:
	Foo(int x) : x(x) {}
	virtual void foo() const { std::cout << "Foo! " << x << "\n"; }

protected:
	int x;
	Foo() {}

private:
	friend class boost::serialization::access;

	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & x;
	}
};
class Bar1 : public Foo {
public:
	Bar1(int x) : Foo(x), bar("Hello!") {}
	virtual void foo() const { std::cout << "Bar1! " << x << " " << bar << "\n"; }

private:
	friend class boost::serialization::access;
	Bar1() {}

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

	std::string bar;
};
class Bar2 : public Foo {
public:
	Bar2(int x) : Foo(x), bar(3.14159265) {}
	virtual void foo() const { std::cout << "Bar2! " << x << "\n"; }

private:
	friend class boost::serialization::access;
	Bar2() {}
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & boost::serialization::base_object<Foo>(*this);
		ar & bar;
	}
	double bar;
};

void printPtrVec(const std::vector<Foo *>& hello) {
	for(std::vector<Foo *>::const_iterator it = hello.begin(); it != hello.end(); ++it) {
		(*it)->foo();
	}
}

int main(int argc, char *argv[]) {
	std::vector<Foo *> hello;
	hello.push_back(new Foo(1));
	hello.push_back(new Bar1(2)); //causes exception
	hello.push_back(new Bar2(3)); //causes exception

	std::ofstream ofs("tmp.txt");
	boost::archive::text_oarchive oa(ofs);
	oa << hello;
	ofs.close();

	printPtrVec(hello);

	std::cout << "Serialized!\n";

	hello.clear();

	std::ifstream ifs("tmp.txt");
	boost::archive::text_iarchive ia(ifs);
	ia >> hello;
	ifs.close();

	std::cout << "Deserialized!\n";

	printPtrVec(hello);

	std::cout << "Successful!\n";
	std::cin.get();

	return 0;
}


Edit: sexier indentation [Edited by - all_names_taken on August 15, 2009 3:51:47 AM]

Share this post


Link to post
Share on other sites
Where does it crash? I have no experience with boost so I'm possibly not in the position to actually help you but does it crash when you push the value, or does it crash later in the program when you have already pushed the value's (now I reread the sentence its really badly formulated:P).

Share this post


Link to post
Share on other sites
You need to export those derived classes :


#include <boost/serialization/export.hpp>

//...

BOOST_CLASS_EXPORT(Bar1);
BOOST_CLASS_EXPORT(Bar2);

//...




This should provide the serialization library with the necessary information to create the correct objects.

Share this post


Link to post
Share on other sites
Great, now it works! I'll have to take a look out how they implemented such an awesome thing!

One more thing I forgot to ask, why do I get this warning when compiling the above program (and the fixed program) with MSVC?

* boost/archive/detail/oserializer.hpp(538) : warning C4099: 'boost::serialization::static_warning_impl<false>::STATIC_WARNING' : type name first seen using 'struct' now seen using 'class'
* boost/serialization/static_warning.hpp(115) : see declaration of 'boost::serialization::static_warning_impl<false>::STATIC_WARNING'
* boost/archive/detail/common_oarchive.hpp(64) : see reference to function template instantiation 'void boost::archive::save<Archive,T>(Archive &,T &)' being compiled
with
[
Archive=boost::archive::text_oarchive,
T=std::vector<Foo *>
]
* boost/archive/basic_text_oarchive.hpp(75) : see reference to function template instantiation 'void boost::archive::detail::common_oarchive<Archive>::save_override<T>(T &,int)' being compiled
with
[
Archive=boost::archive::text_oarchive,
T=std::vector<Foo *>
]
* boost/archive/detail/interface_oarchive.hpp(64) : see reference to function template instantiation 'void boost::archive::basic_text_oarchive<Archive>::save_override<T>(T &,int)' being compiled
with
[
Archive=boost::archive::text_oarchive,
T=std::vector<Foo *>
]
.\main.cpp(107) : see reference to function template instantiation 'Archive &boost::archive::detail::interface_oarchive<Archive>::operator <<<std::vector<_Ty>>(T &)' being compiled
with
[
Archive=boost::archive::text_oarchive,
_Ty=Foo *,
T=std::vector<Foo *>
]

Share this post


Link to post
Share on other sites
This is a warning generated by boost.serialisation in two circumstances, when you are serialising an object with tracking set to boost::serialization::track_never or when you are serialising a non-const object which isn't marked as boost::serialization::track_never, it is designed to trap possible errors with using the library. Here is a rationale behind it.

You are doing the latter. If you const_cast your object before serialising it you can remove the warning :


oa << const_cast<const std::vector<Foo *>&>(hello);



You can read more about object tracking (including the default tracking levels) here.

Good luck!

Share this post


Link to post
Share on other sites

This topic is 3045 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this