使用boost :: serialization序列化unique_ptr的std :: vector在linux上失败

时间:2018-04-26 08:30:44

标签: c++ serialization boost containers unique-ptr

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

#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());

}

根据注释的规定,当尝试将输入存档中的deserialize运算符用于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&#39> new_allocator.h 第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):

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

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

以下CMakeLists.txt用于项目:

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})

1 个答案:

答案 0 :(得分:1)

您无需为矢量提供序列化。事实上,这样做是因为你没有在序列化函数中提供NVP包装而破坏了它。

删除它。

接下来,Serialization不期望(唯一指针)原始类型。出于这个原因,在这个例子中,无论你使用int还是一些简单的结构X 都很重要。

  
    

旁注:您需要在(反)序列化上使用一致的XML名称。您有v_outv_in无效。

  

修正样本:

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

替代地

要进行非侵入式序列化:

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);
    }
} }

<强> Live On Coliru