Как я могу сериализовать std::type_info, используя сериализацию Boost?
Я хочу записать std::type_info
переменной, так что при загрузке я смогу воссоздать соответствующую переменную типа.
Сохранение будет выглядеть так:
friend class boost::serialization::access;
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
...
ar & BOOST_SERIALIZATION_NVP(typeid(value));
ar & BOOST_SERIALIZATION_NVP(value);
...
}
Загрузка будет выглядеть так:
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
...
std::type_info currentType;
ar & BOOST_SERIALIZATION_NVP(currentType);
if(currentType.name() == typeid(std::string).name())
{
std::string value;
ar & BOOST_SERIALIZATION_NVP(value);
//this next line is why I need to read back the type
someObject.setValue<std::string>(value);
}
... //else if for all other types
}
Или, если у вас есть какие-либо другие идеи для решения этой проблемы, я открыт для предложений. Я чувствую, что поступаю неправильно.
1 ответ
Я не знаю, если это именно то, что вы ищете, и это, безусловно, отличается от того, что вы до сих пор, так что YMMV... но в прошлом я достиг аналогичной цели путем создания иерархии типов и затем использование способности Boost.Serialization для автоматической сериализации / десериализации указателя на полиморфный тип. Это дает преимущество, заключающееся в том, что в вашем коде не нужно ничего смешивать с RTTI (библиотека может выполнять RTTI под капотом - я не уверен), но у него есть несколько недостатков.
С одной стороны, это, безусловно, делает код более сложным IMO. Вы можете иметь дело с типами в коде, которые вы не можете легко изменить или создать в иерархии. Вы также можете не захотеть принять (относительно небольшое) снижение производительности полиморфизма и выделения кучи.
Вот более или менее полный пример. Шаблон посетителей здесь полезен, так как вам может понадобиться очень тонкая оболочка для существующих типов, которая может не иметь ничего общего:
#include <boost/serialization/export.hpp>
class Visitor;
class Base
{
public:
virtual ~Base() { }
virtual void accept(const Visitor & v) = 0;
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{ }
};
/* specialization for one set of types */
class Type1 : public Base
{
public:
virtual ~Type1() { }
virtual void accept(const Visitor & v) { ... }
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<Base>(*this);
ar & m_dataType1;
ar & m_dataType2;
//etc...
}
//member data follows...
};
/* specialization for some other set of types */
class Type2 : public Base
{
public:
virtual ~Type2() { }
virtual void accept(const Visitor & v) { ... }
protected:
friend class boost::serialization::access;
template <typename Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & boost::serialization::base_object<Base>(*this);
ar & m_dataType1;
ar & m_dataType2;
//etc...
}
};
BOOST_CLASS_EXPORT_GUID(Type1, "Type1")
BOOST_CLASS_EXPORT_GUID(Type2, "Type2")
BOOST_CLASS_EXPORT_GUID
требуется "зарегистрировать" производные типы в библиотеке, чтобы они могли однозначно идентифицировать их в архиве. Более полное объяснение см. В разделе "Указатели на объекты производных классов" на этой странице.
Теперь вы можете сериализовать и десериализовать, используя указатель на базовый класс (может даже использоваться shared_ptr
;) и использовать шаблон посетителя (или другой метод) для доступа к данным посредством полиморфизма во время выполнения, например:
boost::shared_ptr<Base> p;
...
p.reset(new Type1(...));
archive << p;
p.reset(new Type2(...));
archive << p;
...
archive >> p; //p now points to a Type1
archive >> p; //p now points to a Type2
Этот вопрос и ответ также могут быть полезны: Увеличить сериализацию с помощью полиморфных архивов.
Надеюсь это поможет!
РЕДАКТИРОВАТЬ: исправил мою ссылку на документы Boost...