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

发布于 2024-09-17 21:17:07 字数 929 浏览 6 评论 0原文

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

或者,如果您对解决此问题有任何其他想法,我愿意接受建议。我觉得我正在以错误的方式处理这件事。

I want to record the std::type_info of a variable so that on load I will be able to re-create the appropriate type variable.

Saving will look like this:

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);
    ...
}

Loading will look like this:

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
}

Or, if you have any other ideas for a way to solve this I am open to suggestions. I feel like I am going about this in the wrong way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

束缚m 2024-09-24 21:17:07

我不知道这是否正是您正在寻找的,这肯定与您迄今为止所拥有的方法不同,所以 YMMV...但在过去我已经完成了一个通过创建类型层次结构,然后使用 Boost.Serialization 的功能自动序列化/反序列化指向多态类型的指针,可以实现类似的目标。这样做的好处是不必在代码中搞乱任何 RTTI(该库可能在​​幕后执行 RTTI - 我不确定),但也有一些缺点。

其一,在我看来,这肯定会让代码变得更加复杂。您可能正在处理代码中无法轻松修改或处理到层次结构中的类型。您也可能不愿意承受多态性和堆分配的(相对较小的)性能损失。

这是一个或多或少完整的示例。访问者模式在这里很有用,因为您可能只需要一个非常薄的包装器来围绕可能没有任何共同点的现有类型:

#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 文档的链接...

I don't know if this is exactly what you're looking for, and this is certainly a different approach from what you have so far, so YMMV... but in the past I have accomplished a similar goal by creating a type hierarchy and then using Boost.Serialization's ability to automatically serialize/deserialize a pointer to a polymorphic type. This has the benefit of not having to muck with any RTTI in your code (the library may be doing RTTI under the hood - I'm not sure), but does have a few drawbacks.

For one, it certainly makes the code more complicated IMO. You may be dealing with types in the code that you can't easily modify or work into a hierarchy. You also may not be willing to take the (relatively small) performance hit of polymorphism and heap allocation.

Here's a more or less complete example. The visitor pattern is useful here since you may want just a very thin wrapper around existing types that might not have anything in common:

#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")

The BOOST_CLASS_EXPORT_GUID is required to "register" the derived types with the library so that it can identify them uniquely within the archive. For a more complete explanation, see the section titled "Pointers to Objects of Derived Classes" on this page

Now you can serialize and deserialize using a pointer to the base class (can even used shared_ptr ;), and use the visitor pattern (or some other method) to access the data via polymorphism at runtime, e.g.:

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

This question and answer may also be useful: Boost Serialization using polymorphic archives

Hope this helps!

EDIT: fixed my link to the Boost docs...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文