boost serialization of stl collection of std unique_ptrs

自闭症网瘾萝莉.ら 提交于 2019-12-04 11:03:49

The problem is that the container deserializer is trying to copy-construct a unique_ptr. To demonstrate, consider the following code which yields the same error:

std::vector< std::unique_ptr<int> > vec;
std::unique_ptr<int> p;
vec.push_back(p); // does not compile!

However, this can be solved using std::move:

vec.push_back(std::move(p)); // ok

The least-effort solution would be using a copy constructible smart pointer instead, for example boost::shared_ptr, which comes with its predefined serialization implementation in boost/serialization/shared_ptr.hpp.


The next solution is to serialize the vector manually inside your class:

//NOTE: this replaces void serialize(...) in gps_position
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
    ar & BOOST_SERIALIZATION_NVP(degrees);
    size_t size = deg_map.size();
    ar & BOOST_SERIALIZATION_NVP(size);
    for( auto it=deg_map.begin(), end=deg_map.end(); it!=end; ++it )
       ar & boost::serialization::make_nvp("item",*it);
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
    ar & BOOST_SERIALIZATION_NVP(degrees);
    size_t size = 0;
    ar & BOOST_SERIALIZATION_NVP(size);
    deg_map.clear();
    deg_map.reserve(size);
    while( size-- >= 0 ) {
        std::unique_ptr<MyDegrees> p;
        ar & boost::serialization::make_nvp("item",p);
        deg_map.push_back(std::move(p));
    }
}
BOOST_SERIALIZATION_SPLIT_MEMBER()

The last solution involves writing your own container serializer, like you did for unique_ptr, that uses std::move to add items:

namespace boost { namespace serialization {
//NOTE: do not include boost/serialization/vector.hpp
template<class Archive, class T, class Allocator>
inline void save(
    Archive & ar,
    const std::vector<T, Allocator> &t,
    const unsigned int
){
    collection_size_type count (t.size());
    ar << BOOST_SERIALIZATION_NVP(count);
    for(auto it=t.begin(), end=t.end(); it!=end; ++it)
        ar << boost::serialization::make_nvp("item", (*it));
}

template<class Archive, class T, class Allocator>
inline void load(
    Archive & ar,
    std::vector<T, Allocator> &t,
    const unsigned int
){
    collection_size_type count;
    ar >> BOOST_SERIALIZATION_NVP(count);
    t.clear();
    t.reserve(count);
    while( count-- > 0 ) {
        T i;
        ar >> boost::serialization::make_nvp("item", i);
        t.push_back(std::move(i)); // use std::move
    }
}

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

And last but not least, you should use:

oa << BOOST_SERIALIZATION_NVP(g);
// and
ia >> BOOST_SERIALIZATION_NVP(newg);

in your TestBasicSerialize() when using the xml archive.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!