一流的加速系列化包装的指针(Boost serialization of class wrappin

2019-10-23 15:21发布

我有一个类Ptr它包装的指针。 这个指针可以处理的结构,例如Ptr<A>其中A可以是一个复杂的结构或原语,如Ptr<double> 。 我想指定saveload的功能Ptr serilaization为这两种情况下工作。
在这里,我试图去模仿一个简单的例子:

struct A { 
    A(int aa) : a(aa) {} 
    int a; 
    template<class Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar & BOOST_SERIALIZATION_NVP(a);
    }
};

template <typename T>
struct Ptr {
    Ptr() : m_elem(0) {}
    Ptr(const T* elem) { m_elem = (elem ? new T(*elem) : 0); };
    const T& operator*() const { return *m_elem; };
    T& operator*()  { return *m_elem; };
    const T* operator->() const { return m_elem;};
    T* operator->() { return m_elem;};

    // [...] other ctor, copy, del, etc...

    T* m_elem;
};

namespace boost { namespace serialization {

template<class Archive, class T>
void save(Archive & ar, const Ptr<T> &ptr, const unsigned int version) {
    T* base_pointer = (ptr.m_elem);
    ar & boost::serialization::make_nvp("Ptr", base_pointer);
}

template<class Archive, class T>
void load(Archive & ar, Ptr<T> &ptr, const unsigned int version) {
    T *base_pointer;
    ar & boost::serialization::make_nvp("Ptr", base_pointer);
    ptr.m_elem = base_pointer;
}

template<class Archive, class T>
void serialize(Archive & ar, Ptr<T> &ptr, const unsigned int version)
{
    boost::serialization::split_free(ar, ptr, version);
}

}} // end namespace

int main() {
    Ptr<A> p1(new A(4));
    std::cout << p1.m_elem->a << std::endl;
    Ptr<double> p2(new double(2.0));
    std::cout << *(p2.m_elem) << std::endl;

    // The serialization for Ptr<A> seems to work
    std::ostringstream archive_ostream;
    boost::archive::xml_oarchive oa(archive_ostream);
    oa << BOOST_SERIALIZATION_NVP(p1); 
    std::cout << archive_ostream.str() << std::endl;

    // Serialization for Ptr<double> does not compile
    /*
    std::ostringstream archive_ostream2;
    boost::archive::xml_oarchive oa2(archive_ostream2);
    oa2 << BOOST_SERIALIZATION_NVP(p2); 
    std::cout << archive_ostream2.str() << std::endl;
    */
}

活生生的例子

正如你所看到的,对于系列化Ptr<A>似乎工作(还是我不知道这是否是足够安全的)。 然而,序列化Ptr<double>不进行编译。

错误输出:

main.cpp中:在“无效的boost ::系列化的实例::保存(归档&,常量PTR&,无符号整型)[带有归档=升压::归档:: xml_oarchive; T = A]':

/usr/local/include/boost/serialization/split_free.hpp:45:13:
从“静态无效的boost ::系列化:: free_saver需要::调用(归档&,常量T&,无符号整型)[带有归档=升压::归档:: xml_oarchive; T = PTR]”

/usr/local/include/boost/serialization/split_free.hpp:74:18:
从“无效的boost ::系列化:: split_free需要(归档&,T&,无符号整型)[带有归档=升压::归档:: xml_oarchive; T = PTR]”

main.cpp中:57:34:从“无效的boost ::系列化::序列化所需的(归档&,PTR&,无符号整型)[带有归档=升压::归档:: xml_oarchive; T = A]”

因此,我要寻找一个正确的Ptr系列化!

Answer 1:

谜语的解决方案是简单地通过一个指针序列化原始类型不被支持。

其原因是,对象跟踪对于原始类型禁用。 这是记录在这里:

特别注意事项/ 目标跟踪

默认情况下,数据类型指定由执行层面类的序列特征原始,无需跟踪。 如果期望通过指针来跟踪共享原始对象(例如一个长用作参考计数),它应被包裹在一个类/结构,以便它是可识别的类型。 改变的执行层面的替代长会影响整个程序序列化的所有渴望 - 也许不是什么人会打算。

下面是显示在隔离的根本原因简约示例:

在Coliru

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <iostream>
#include <sstream>

int main() {
    // Serialization for double* does not compile
    double* p(new double(2.0));
    std::cout << *p << std::endl;

    std::ostringstream oss;
    boost::archive::xml_oarchive oa(oss);
    oa << BOOST_SERIALIZATION_NVP(p); 
    std::cout << oss.str() << std::endl;
}

你需要重新考虑你的系列化计划。 你希望成为什么对象标识/需要跟踪?

您可以跟踪的身份Ptr<>对象,并从你不嫌麻烦toimplement自定义指针包装类型的事实,我得到的印象,这可能是你想要/需要。

演示: 住在Coliru

在你真正想要的双级对象追踪这里万一(例如,如果你可以有两个Ptr<T>指向相同的情况下T ?),你将需要部分专门用于其中T为基本类型的情况。



文章来源: Boost serialization of class wrapping a pointer