【问题标题】:How can I serialize std::type_info using Boost serialization?如何使用 Boost 序列化序列化 std::type_info?
【发布时间】:2010-09-08 17:03:49
【问题描述】:

我想记录变量的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
}

或者,如果您对解决此问题的方法有任何其他想法,我愿意接受建议。我觉得我做错了。

【问题讨论】:

    标签: serialization boost rtti


    【解决方案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 文档的链接...

    【讨论】:

    • 非常感谢您的回复!这种方法肯定会摆脱我对 rtti 的依赖,这很棒,但它会添加一堆我真的不想添加的新类。我现在有大约 8 种不同的类型,以后可能还会更多。我现在所做的不是序列化std::type_info,而是序列化std::type_info.name(),然后在反序列化时比较字符串。不是最漂亮的解决方案,但我认为它可以满足我的需求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 2023-03-15
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多