Как я могу сериализовать std :: type_info, используя сериализацию Boost? - PullRequest
2 голосов
/ 08 сентября 2010

Я хочу записать 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 Ответ

1 голос
/ 09 сентября 2010

Я не знаю, если это именно то, что вы ищете, и это, безусловно, отличается подход от того, что у вас есть, так что 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 ...

...