Ускорить сериализацию всех производных типов динамически

57
7

BOOST_CLASS_EXPORT() абсолютно необходимо называть BOOST_CLASS_EXPORT() или register_type() для всех производных типов виртуального базового класса? Есть ли способ указать базовый класс?

Вот пример кода (я использую boost 1.59):

    #include <iostream>
#include <string>
#include <memory>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
//#include <boost/make_shared.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>

class Parent {
public:
int test_val = 1234234;

int p() { return 13294; }
virtual void testing() = 0;
int get_test_val() {
std::cout << __PRETTY_FUNCTION__ << ":" << test_val << "\n";
return test_val;
}

template <class Archive> void serialize(Archive &ar, unsigned) {
ar & test_val;
}
};

//BOOST_SERIALIZATION_ASSUME_ABSTRACT(Parent)

class RefMem : public Parent {
public:
RefMem() {
test_val = 12342;
std::cout << __PRETTY_FUNCTION__ << ":" << test_val << "\n";
}
void testing() {
std::cout << "TEST" << std::endl;
}
template<class Archive> void serialize(Archive &ar, unsigned) {
ar & boost::serialization::base_object<Parent>(*this);
}
};

class RefMem2 : public Parent {
public:
RefMem2() {
test_val = 9823;
std::cout << __PRETTY_FUNCTION__ << ":" << test_val << "\n";
}

void testing() {
std::cout << "TEST2" << std::endl;
}
template<class Archive> void serialize(Archive &ar, unsigned) {
ar & boost::serialization::base_object<Parent>(*this);
}
};
using ParentRef = std::shared_ptr<Parent>;

class Test {
public:
int t_ = 0;
ParentRef parent_;

Test(int t = 0, ParentRef parent = std::make_shared<RefMem>()) : t_(t), parent_(parent) { }

template <class Archive> void serialize(Archive &ar, const unsigned int file_version) {
ar & t_ & parent_;
}
};

//BOOST_CLASS_EXPORT(RefMem)

#include <sstream>

int main() {
ParentRef the_instance = std::make_shared<RefMem>();

Test test = Test(50, the_instance);

std::cout << "t_: " << test.t_ << "\n";
std::cout << "Test val: " << test.parent_->get_test_val() << "\n";
std::ostringstream oss;
{
boost::archive::text_oarchive oa(oss);
oa.register_type<RefMem>();
oa.register_type<RefMem2>();
oa << the_instance << test; // NOTE SERIALIZE test AS-IF A POINTER
}

{
ParentRef the_cloned_instance;
Test cloned;

std::istringstream iss(oss.str());
{
boost::archive::text_iarchive ia(iss);
ia.register_type<RefMem>();
ia.register_type<RefMem2>();
ia >> the_cloned_instance >> cloned;
}

std::cout << "t_: " << cloned.t_ << "\n";
std::cout << "Test val: " << cloned.parent_->get_test_val() << "\n";
std::cout << "Are Parent objects aliasing: " << std::boolalpha <<
(cloned.parent_ == the_cloned_instance) << "\n";
}
}

спросил(а) 2015-09-09T01:17:00+03:00 5 лет назад
1
Решение
57

Да, это необходимо.

Вы уже видите механиков. Макрос - это всего лишь способ автоматизировать танец register_type для типов архивов, известных во время расширения макроса.

Вы могли бы в этом случае уйти с перечислением типов в методе сериализации Test, который был бы "как раз вовремя" - при условии, что вы не десериализуете Parent полиморфные экземпляры до этого.

Это также работает:

class Test {
public:
int t_ = 0;
ParentRef parent_;

Test(int t = 0, ParentRef parent = std::make_shared<RefMem1>()) : t_(t), parent_(parent) {}

template <class Archive> void serialize(Archive &ar, unsigned) {
ar.template register_type<RefMem1>();
ar.template register_type<RefMem2>();
ar & t_ & parent_;
}
};

Iff вы меняете порядок архива:

    oa << test << the_instance;
// ...
ia >> cloned >> the_cloned_instance;

См. Live On Coliru

ответил(а) 2015-09-09T12:04:00+03:00 5 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема