首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将boost::serialization与来自C++的std::unique_ptr一起使用

如何将boost::serialization与来自C++的std::unique_ptr一起使用
EN

Stack Overflow用户
提问于 2020-02-21 23:16:55
回答 2查看 168关注 0票数 0

我正在尝试使用boost::serialization库来序列化一个包含std::unique_ptr成员的类(下面代码中的类A)。

环境:

操作系统: Windows 10 1909

IDE: Microsoft Visual Studio Community 2019版本16.4.4

库: boost-serialization 1.72.0 (随vcpkg工具安装)

代码语言:javascript
复制
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
#include <iostream>
#include <memory>

using namespace std;
using namespace boost;

class A
{
public:
    A()
    {
    }

    A(int input_size, int input_value)                  //  Constructor
    {
        this->data = std::make_unique<int[]>(input_size);
        this->size = input_size;
        for (int loop_number = 0; loop_number < size; loop_number++) {
            data[loop_number] = input_value;
        }
    }

    std::unique_ptr<int[]> get_data()
    {
        //  deep copy
        auto return_data = std::make_unique<int[]>(size);
        for (int loop_number = 0; loop_number < size; loop_number++) {
            return_data[loop_number] = data[loop_number];
        }
        return return_data;
    }
    int get_size()
    {
        return this->size;
    }
    ~A()
    {
    }
private:
    std::unique_ptr<int[]> data;
    int size;
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive& ar, const unsigned int version)
    {
        ar& data;
        ar& size;
    }
};


int main()
{
    // create and open a character archive for output
    std::ofstream ofs("filename");

    // create class instance
    const A a_object(10, 5);

    // save data to archive
    {
        boost::archive::text_oarchive oa(ofs);
        // write class instance to archive
        oa << a_object;
        // archive and stream closed when destructors are called
    }

    // ... some time later restore the class instance to its orginal state
    A load_from_file;
    {
        // create and open an archive for input
        std::ifstream ifs("filename");
        boost::archive::text_iarchive ia(ifs);
        // read class state from archive
        ia >> load_from_file;
        // archive and stream closed when destructors are called
    }
    return 0;
}

编译器抛出C2440错误,错误消息为'initializing': cannot convert from 'int *' to 'const T (*const )'。它是指%includePath%\boost\serialization\unique_ptr.hpp

代码语言:javascript
复制
template<class Archive, class T>
inline void save(
    Archive & ar,
    const std::unique_ptr< T > &t,
    const unsigned int /*file_version*/
){
    // only the raw pointer has to be saved
    // the ref count is rebuilt automatically on load
    const T * const tx = t.get();
    ar << BOOST_SERIALIZATION_NVP(tx);
}

似乎std::unique_ptr在boost-serialization库(1.72.0版)中仍然无法成功序列化?此外,有没有什么解决方案可以序列化带有std::unique_ptr成员的类?

EN

回答 2

Stack Overflow用户

发布于 2020-02-24 22:38:15

基于"serialize“模板函数中用于保存/加载数据成员的std::unique_ptr doesn't stored sizear& data;不能被序列化的事实,因为该行中的数据计数是未知的。

代码语言:javascript
复制
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
    ar& data;        //    <==    the count of data is unknown 
    ar& size;
}

为了访问所有有效数据,需要执行智能指针" data“的迭代过程(如下面的代码所示)。

代码语言:javascript
复制
for (int i = 0; i < size; ++i)
        ar& data[i];

因此,保存部分如下所示。

代码语言:javascript
复制
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    ar& size;
    for (int i = 0; i < size; ++i)
        ar& data[i];
}

对于加载部分,重要的是在加载数据之前分配智能指针的空间,以避免访问冲突错误

代码语言:javascript
复制
template<class Archive>
void load(Archive& ar, const unsigned int version)
{
    ar& size;
    data = std::make_unique<int[]>(size);    //    <==    allocate space of smart pointer first
    for (int i = 0; i < size; ++i)
        ar& data[i];
}

注意:宏BOOST_SERIALIZATION_SPLIT_MEMBER()需要放入,因为保存/加载函数被拆分了。

最后,类A中的序列化部分可以像下面的代码一样完成。

代码语言:javascript
复制
friend class boost::serialization::access;
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
    ar& size;
    for (int i = 0; i < size; ++i)
        ar& data[i];
}
template<class Archive>
void load(Archive& ar, const unsigned int version)
{
    ar& size;
    data = std::make_unique<int[]>(size);
    for (int i = 0; i < size; ++i)
        ar& data[i];
}
BOOST_SERIALIZATION_SPLIT_MEMBER()

参考:Boost serialization tutorial

票数 1
EN

Stack Overflow用户

发布于 2020-02-22 00:04:26

根据您使用的Boost版本,您可能需要实现自己的非侵入式适配器,如下所示:

代码语言:javascript
复制
namespace boost { 
namespace serialization {

template<class Archive, class T>
inline void save( Archive & ar, const std::unique_ptr< T > &t, const unsigned int /*file_version*/){
    // only the raw pointer has to be saved
    const T * const base_pointer = t.get();
    ar & BOOST_SERIALIZATION_NVP(base_pointer);
}

template<class Archive, class T>
inline void load(Archive & ar,std::unique_ptr< T > &t, const unsigned int /*file_version*/){
    T *base_pointer;
    ar & BOOST_SERIALIZATION_NVP(base_pointer);
    t.reset(base_pointer);
}

template<class Archive, class T>
inline void serialize(Archive & ar,std::unique_ptr< T > &t, const unsigned int file_version){
    boost::serialization::split_free(ar, t, file_version);
}

} // namespace serialization
} // namespace boost

有关完整的示例,请参阅this

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60341575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档