使用 boost::序列化序列化 std::vector of unique_ptr 在 Linux 上失败



我在使用 std::vector of std::unique_ptr 的 upgrade 序列化时遇到了问题。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());
}

如注释所述,当尝试将反序列化运算符从输入存档使用到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 行中。

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 16.04.0 在 Ubuntu 5.4.0 上进行编译

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

无需为向量提供序列化。事实上,这样做会破坏事情,因为您未能在序列化函数中提供 NVP 包装。

只需删除它。

接下来,序列化不需要(唯一指针)到基元类型。出于这个原因,在这个例子中,你使用int还是一些琐碎的结构X确实很重要。

旁注:在(反)序列化时需要一致的 XML 名称。你有v_outv_in,这是行不通的。

固定样本:

住在科里鲁

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

住在科里鲁

最新更新