代码之家  ›  专栏  ›  技术社区  ›  NeilMonday

如何使用boost序列化来序列化std::type_info?

  •  2
  • NeilMonday  · 技术社区  · 15 年前

    我想录下 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 回复  |  直到 15 年前
        1
  •  1
  •   Community Mohan Dere    9 年前

    我不知道这是否正是你要找的,这当然是 不同的 从你目前的情况来看,所以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文档的链接…