【问题标题】:reference_wrapper to abstract class serialization in boostreference_wrapper 到 boost 中的抽象类序列化
【发布时间】:2015-05-17 11:30:18
【问题描述】:

我必须在抽象类的 Boost 向量(或任何其他容器)中序列化。 因为不可能直接创建抽象类的向量,所以我为这个抽象类创建了reference_wrapper的向量。

但是如何在 Boost std::reference_wrapper 中序列化为抽象类?当我尝试直接执行此操作时,出现错误,reference_wrapper 的默认构造函数不可访问。

提前致谢。

【问题讨论】:

  • 您愿意创建一个 MCVE 吗?
  • 不,什么是 MCVE?如何创建它?我在谷歌上找不到任何关于它的信息。
  • 好的。我试图变得时髦和get with the times。只需创建一个SSCCE

标签: serialization boost reference-wrapper


【解决方案1】:

多想一下你就不想序列化引用了。

由于逻辑上的引用是不可重新安装的,并且不“保存任何数据”,它们永远不会被“反序列化”(它们指向什么?临时对象?泄漏的堆对象?)。

当然reference_wrappers 可重新安装的,但在这种情况下,您真的只是将它们用作原始指针(可能拥有指针)。

在这种情况下,只需将它们序列化为指针,并可选择使用对象跟踪来防止重复(反)序列化。

提示我认为你会从 boost::ptr_vector 中受益,它内置了序列化支持。见下文(和 docs


演示

同时提出一种简单的方法来“教导”Boost 序列化以将reference_wrapper 用作原始指针(这可能是您需要的):

Live On Coliru

/////////////////////////////////////////////////
// Allow serialization of `reference_wrapper`
namespace boost { namespace serialization {
    template<class Ar, class T> void save_construct_data(Ar & ar, std::reference_wrapper<T> const * t, unsigned) {
        T const * p = &t->get();
        ar << p;
    }
    template<class Ar, class T> void load_construct_data(Ar & ar, std::reference_wrapper<T> * t, unsigned) {
        T* p = nullptr;
        ar >> p;
        ::new(t) std::reference_wrapper<T>(*p);
    }

    template <class Ar, typename T> inline void serialize(Ar &, std::reference_wrapper<T>&, unsigned) { }
} }

但是,我发现reference_wrapper 不是默认可构造的事实存在一个更大的问题,这对 std::vector 的反序列化方式造成了严重破坏。

当你指的是指针时,我会简化并只使用指针:

Live On Coliru

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>

#include <boost/ptr_container/serialize_ptr_vector.hpp>
#include <functional>

using namespace boost;

/////////////////////////////////////////////////
// defining a virtual class hierarchy...
struct B {
    virtual ~B() = default;
    virtual std::ostream& print(std::ostream& os) const { return os << __PRETTY_FUNCTION__; }

  private:
    friend class boost::serialization::access;
    template <typename Ar> void serialize(Ar&, unsigned) const {
    }
};

struct D1 : B {
    virtual std::ostream& print(std::ostream& os) const { return os << _data; }

  private:
    std::string _data = "forty two";

    friend class boost::serialization::access;
    template <typename Ar> void serialize(Ar& ar, unsigned) {
        ar & boost::serialization::base_object<B>(*this);
        ar & _data;
    }
};

struct D2 : B {
    virtual std::ostream& print(std::ostream& os) const { return os << _data; }

  private:
    int _data = 42;

    friend class boost::serialization::access;
    template <typename Ar> void serialize(Ar& ar, unsigned) {
        ar & boost::serialization::base_object<B>(*this);
        ar & _data;
    }
};

BOOST_CLASS_EXPORT(B)
BOOST_CLASS_EXPORT(D1)
BOOST_CLASS_EXPORT(D2)

/////////////////////////////////////////////////
// sample data structure representing our program

struct Data {
    ptr_vector<B> storage;
    std::vector<B*> refvect;

    void fill_sample() {
        storage.push_back(new D1);
        storage.push_back(new D1);
        storage.push_back(new D2);
        storage.push_back(new D1);

        refvect.clear();
        for (auto it = storage.rbegin(); it != storage.rend(); ++it)
            refvect.push_back(&*it);
    }

    friend std::ostream& operator<<(std::ostream& os, Data const& data) {
        for (auto i : data.refvect) i->print(std::cout) << "\n";
        return os;
    }

    template <typename Ar> void serialize(Ar& ar, unsigned) {
        ar & storage & refvect;
    }
};

#include <sstream>
int main() {

    std::stringstream stream;
    {
        archive::binary_oarchive oa(stream);

        Data x;
        x.fill_sample();
        oa << x;

        std::cout << "Before:\n" << x << "\n";
    }

    {
        archive::binary_iarchive ia(stream);

        Data y;
        ia >> y;
        std::cout << "After:\n" << y << "\n";
    }

}

打印

Before:
forty two
42
forty two
forty two

After:
forty two
42
forty two
forty two

【讨论】:

    猜你喜欢
    • 2019-02-19
    • 2010-10-12
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2019-08-12
    相关资源
    最近更新 更多