如何使用Boost序列化序列化std :: type_info?

时间:2010-09-08 17:03:49

标签: serialization boost rtti

我想记录变量的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 个答案:

答案 0 :(得分: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需要使用库“注册”派生类型,以便它可以在归档中唯一地标识它们。有关更完整的说明,请参阅this page上标题为“派生类对象的指针”的部分

现在,您可以使用指向基类的指针进行序列化和反序列化(甚至可以使用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 Serialization using polymorphic archives

希望这有帮助!

编辑:修复了我对Boost文档的链接...