В документации есть раздел, в котором описывается, как (де) сериализовать классы с конструкторами не по умолчанию. Смотрите здесь .
По сути, вы должны реализовать две функции с именами save_construct_data
и load_construct_data
в пространстве имен boost::serialization
, чтобы записывать и считывать данные, используемые для создания экземпляров вашего класса. Затем можно вызвать конструктор не по умолчанию Foo
из функции load_construct_data
с параметрами, необходимыми для восстановления объекта Foo
.
Вот рабочий пример, основанный на вашем обновленном коде:
Обратите внимание, что я использовал shared_ptr
, чтобы уточнить, что член data
, сериализованный Foo и Bar, ссылается на одно и то же.
#include <vector>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <sstream>
struct Foo {
struct Bar {
boost::shared_ptr< std::vector<int> > data; // Must point to Foo::data
Bar( boost::shared_ptr< std::vector<int> > d ) : data(d) { }
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// ** note that this is empty **
}
};
boost::shared_ptr< std::vector<int> > data;
std::vector<Bar> elements;
Foo() : data( new std::vector<int>() ) {
std::cerr << "Running default constructor" << std::endl;
data->push_back(1);
data->push_back(2);
data->push_back(3);
data->push_back(4);
data->push_back(5);
elements.push_back( Bar( data ) );
elements.push_back( Bar( data ) );
elements.push_back( Bar( data ) );
}
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
// ** note that this is empty **
}
Foo(
boost::shared_ptr< std::vector<int> > const & data_,
std::vector<Bar> const & elements_ ) : data( data_ ), elements( elements_ )
{
std::cout << "cheap construction" << std::endl;
}
};
namespace boost { namespace serialization {
template<class Archive>
inline void save_construct_data(
Archive & ar, const Foo * foo, const unsigned int file_version
){
ar << foo->data << foo->elements;
}
template<class Archive>
inline void load_construct_data(
Archive & ar, Foo * foo, const unsigned int file_version
){
boost::shared_ptr< std::vector<int> > data;
std::vector<Foo::Bar> elements;
ar >> data >> elements;
::new(foo)Foo(data, elements);
}
template<class Archive>
inline void save_construct_data(
Archive & ar, const Foo::Bar * bar, const unsigned int file_version
){
ar << bar->data;
}
template<class Archive>
inline void load_construct_data(
Archive & ar, Foo::Bar * bar, const unsigned int file_version
){
boost::shared_ptr< std::vector<int> > data;
ar >> data;
::new(bar)Foo::Bar(data);
}
}}
int main()
{
std::stringstream ss;
{
boost::scoped_ptr< Foo > foo( new Foo() );
std::cout << "size before serialization is: " << foo->data->size() << std::endl;
boost::archive::text_oarchive oa(ss);
oa << foo;
}
{
boost::scoped_ptr< Foo > foo;
boost::archive::text_iarchive is(ss);
is >> foo;
std::cout << "size after deserialization is: " << foo->data->size() << std::endl;
}
return 0;
}