在Linux上使用boost :: serialization序列化unique_ptr的std :: vector失败 [英] Serializing std::vector of unique_ptr using boost::serialization fails on linux

查看:249
本文介绍了在Linux上使用boost :: serialization序列化unique_ptr的std :: vector失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用std :: unique_ptr的std :: vector的boost序列化时遇到问题。 unique_ptr的类型无关紧要,在下面的示例中,将使用整数:

I am encountering an issue with using boost serialization of a std::vector of std::unique_ptr's. The type of the unique_ptr does not matter, and in the below example, integers are used:

#include <boost/serialization/unique_ptr.hpp>

#include <boost/serialization/vector.hpp>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <fstream>

namespace boost {
namespace serialization {

template <class Archive>
void serialize(Archive& ar, std::vector<unique_ptr<int>>& g, const unsigned int version) {
    ar& g;
}

}  // namespace serialization
}  // namespace boost

int main(int argc, char** argv){
std::vector<std::unique_ptr<int>> v_out;
const std::string archName = "test_arch.xml";

v_out.push_back(make_unique<int>(1));
v_out.push_back(make_unique<int>(2));
v_out.push_back(make_unique<int>(3));

// Serialize vector
std::ofstream ofs(archName);
{
    boost::archive::xml_oarchive oa(ofs);
    oa << BOOST_SERIALIZATION_NVP(v_out);
}
ofs.close();

std::vector<std::unique_ptr<int>> v_in;
// Deserialize vector
std::ifstream ifs(archName);
{
    boost::archive::xml_iarchive ia(ifs);
    // next line fails to build
    ia >> BOOST_SERIALIZATION_NVP(v_in);
}
ifs.close();


remove(archName.c_str());

}

如注释所指定,程序在以下情况下无法编译尝试使用输入档案中的反序列化运算符进入 std :: vector< std :: unique_ptr< ...>>

As specified by the comment, the program fails to compile when trying to use the deserialize operator from the input archive into a std::vector<std::unique_ptr<...>>.

抛出的错误是:

/usr/include/c++/5/ext/new_allocator.h:120: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^

这是在GCC的 new_allocator.h 中抛出的,第120行。

which is thrown in GCC's new_allocator.h, line 120.

116: #if __cplusplus >= 201103L
117:       template<typename _Up, typename... _Args>
118:         void
119:         construct(_Up* __p, _Args&&... __args)
120:    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
121: 
122:       template<typename _Up>
123:         void 
124:         destroy(_Up* __p) { __p->~_Up(); }
125: #else
126: ...

上面的示例构建并在Windows和OS X上均按预期方式运行-仅在Linux上无法编译。

该应用程序已链接到以下库(使用CMake):

The above example build and runs as expected on both Windows and OS X - This only fails to compile on linux.
The app is linked to the following libraries (using CMake):

target_link_libraries(app ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SERIALIZATION_LIBRARY})

在所有平台上,链接命令均相等。
我正在使用boost 1.67并在Ubuntu 16.04上使用GCC 5.4.0进行编译

The link command is equal on all platforms. I am using boost 1.67 and compiling on Ubuntu 16.04 using GCC 5.4.0

以下CMakeLists.txt用于该项目:

The following CMakeLists.txt is used for the project:

set (CMAKE_CXX_STANDARD 14)

add_executable(test main.cpp)

set(Boost_NO_SYSTEM_PATHS OFF)
set(BOOST_INCLUDEDIR "$ENV{BOOST_ROOT}")

find_package(Boost COMPONENTS serialization REQUIRED)

target_link_libraries(test  ${Boost_SERIALIZATION_LIBRARY})


推荐答案

您不需要为向量提供序列化。实际上,这样做会失败,因为您无法在序列化函数中提供NVP包装。

You don't need to provide serialization for the vector. In fact, doing so broke things because you failed to provide NVP wrapping in your serialize function.

只需删除该内容即可。

接下来,序列化不期望(唯一的指针)原始类型。因此,在此示例中,确实很重要,无论您使用 int 还是某些琐碎的结构 X

Next up, Serialization does not expect (unique pointers) to primitive types. For that reason in this example it does matter whether you use int or some trivial struct X.



侧面说明:在(反)序列化时需要一致的XML名称。您有 v_out v_in 无效的地方。


固定示例:

在Coliru上直播

#include <boost/serialization/unique_ptr.hpp>

#include <boost/serialization/vector.hpp>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <fstream>
#include <memory>

struct X {
    X(int = 0) {}
    template <typename Ar> void serialize(Ar&, unsigned) {}
};

int main() {
    std::vector<std::unique_ptr<X> > v_out;
    const std::string archName = "test_arch.xml";

    v_out.push_back(std::make_unique<X>(1));
    v_out.push_back(std::make_unique<X>(2));
    v_out.push_back(std::make_unique<X>(3));

    // Serialize vector
    {
        std::ofstream ofs(archName);
        boost::archive::xml_oarchive oa(ofs);
        oa << boost::serialization::make_nvp("root", v_out);
    }

    // Deserialize vector
    {
        std::ifstream ifs(archName);
        boost::archive::xml_iarchive ia(ifs);
        // next line fails to build
        std::vector<std::unique_ptr<X> > v_in;
        ia >> boost::serialization::make_nvp("root", v_in);
    }

    remove(archName.c_str());
}



或者



要进行非侵入式序列化:

Alternatively

To have non-intrusive serialization:

struct X {
    X(int i = 0) : _i(i) {}
    int _i;
};

namespace boost { namespace serialization {
    template <class Archive>
    void serialize(Archive& ar, X& x, unsigned) {
        ar& BOOST_SERIALIZATION_NVP(x._i);
    }
} }

在Coliru上直播

这篇关于在Linux上使用boost :: serialization序列化unique_ptr的std :: vector失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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