Boost序列化包装一个指针的类 [英] Boost serialization of class wrapping a pointer

查看:178
本文介绍了Boost序列化包装一个指针的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类 Ptr ,它包含一个指针。
该指针可以处理诸如 Ptr< A> 之类的结构,其中 A 可以是复杂结构或原语例如 Ptr< double> 。我想指定 ptr 保存加载函数

这里我尝试重现一个简化的例子:

I have a class Ptr which wraps a pointer. This pointer can handle structures such as Ptr<A> where A can be a complex structure or primitives such as Ptr<double>. I would like to specify the save and load functions of Ptr serilaization to work for both of these cases.
Here I try to reproduce a simplified example :

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;
    */
}

Live example

正如你所看到的, Ptr< A> 似乎工作(仍然我不知道如果它是否足够安全)。但是, Ptr 的序列化不会编译。

As you can see, the serialization for Ptr<A> seems to work (still I am not sure if it is safe enough). However, serialization for Ptr<double> is not compiling.

错误输出是:


main.cpp:在实例化'void
boost :: serialization :: save(Archive& const Ptr& unsigned int)
[with Archive = boost :: archive :: xml_oarchive; T = A]':

main.cpp: In instantiation of 'void boost::serialization::save(Archive&, const Ptr&, unsigned int) [with Archive = boost::archive::xml_oarchive; T = A]':

/usr/local/include/boost/serialization/split_free.hpp:45:13:

要求' static void boost :: serialization :: free_saver :: invoke(Archive& const T& unsigned int)[with Archive =
boost :: archive :: xml_oarchive; T = Ptr]'

/usr/local/include/boost/serialization/split_free.hpp:45:13:
required from 'static void boost::serialization::free_saver::invoke(Archive&, const T&, unsigned int) [with Archive = boost::archive::xml_oarchive; T = Ptr]'

/usr/local/include/boost/serialization/split_free.hpp:74:18:

需要从'void boost :: serialization :: split_free(Archive& T;&
unsigned int)[with Archive = boost :: archive :: xml_oarchive; T:
Ptr]'

/usr/local/include/boost/serialization/split_free.hpp:74:18:
required from 'void boost::serialization::split_free(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_oarchive; T = Ptr]'

main.cpp:57:34:需要从'void
boost :: serialization :: serialize(Archive& ,Ptr& unsigned int)[with
Archive = boost :: archive :: xml_oarchive; T = A]'

main.cpp:57:34: required from 'void boost::serialization::serialize(Archive&, Ptr&, unsigned int) [with Archive = boost::archive::xml_oarchive; T = A]'

因此,我正在寻找一个正确的 Ptr

Hence I am looking for a correct Ptr serialization !

推荐答案

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

The solution to the riddle is simply that serializing primitive types through a pointer is not supported.

原因是对原始类型禁用对象跟踪。此处记录如下:

The reason is that object tracking is disabled for primitive types. this is documented here:


特殊注意事项/ 对象跟踪



默认情况下,由实现级别指定的数据类型从不跟踪类序列化trait。如果希望通过指针(例如长的用作引用计数)来跟踪共享的基本对象,则它应该被包装在类/结构中,使得它是可识别的类型。改变long的实现级别的选择将影响整个程序中序列化的所有long - 可能不是一个意图。

Special Considerations / Object Tracking

By default, data types designated primitive by Implementation Level class serialization trait are never tracked. If it is desired to track a shared primitive object through a pointer (e.g. a long used as a reference count), It should be wrapped in a class/struct so that it is an identifiable type. The alternative of changing the implementation level of a long would affect all longs serialized in the whole program - probably not what one would intend.

这是一个简单的示例,显示孤立的根本原因:

Here's a minimalist sample that shows the root cause in isolation:

Live On Coliru

Live On 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;
}

您需要重新思考您的序列化计划。您希望/需要跟踪什么对象身份?

You need to rethink your serialization plan. What object identity do you wish/need to track?

您可以跟踪 Ptr<> 对象,并且由于你花费了麻烦来实现自定义指针包装类型,我得到这个可能是你想要/需要的印象。

You can track the identity of the Ptr<> object, and from the fact that you took the trouble toimplement a custom pointer wrapper type, I get the impression that this is likely all you want/need.

演示: strong> Live On Coliru

Demo: Live On Coliru

在这种情况下,你真的想要双层对象跟踪(例如,如果你可以有两个 Ptr< T> 实例指向相同的 T ?)你将需要部分专门化的情况下,T是一个原始类型。

In the unlikely event that you really want bi-level object tracking here (e.g. if you can have two Ptr<T> instances pointing to the same T?) you will need to partially specialize for the case where T is a primitive type.

这篇关于Boost序列化包装一个指针的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆