加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – boost :: serialization:具有私有默认构造函数的对象在向

发布时间:2020-12-16 09:58:04 所属栏目:百科 来源:网络整理
导读:请考虑以下代码: #include boost/serialization/nvp.hpp#include boost/archive/xml_iarchive.hpp#include boost/archive/xml_oarchive.hppclass Foo{ friend class boost::serialization::access; templateclass Archive void serialize(Archive ar,const
请考虑以下代码:

#include <boost/serialization/nvp.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>

class Foo{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar,const unsigned int)
    {
        ar & BOOST_SERIALIZATION_NVP(i);
    }
    int i;
    Foo():i(0){}
public:
    Foo(int k):i(k){}
};

int main(int argc,char *argv[])
{
    std::vector< Foo> f;
    f.push_back(Foo(12));
    std::ofstream os("path");
    boost::archive::xml_oarchive oa(os);
    oa << boost::serialization::make_nvp("f",f);
    os.close();
    std::vector<Foo> g;
    std::ifstream is("path");
    boost::archive::xml_iarchive ia(is);
    ia >> boost::serialization::make_nvp("f",g);
}

这在序列化Foos矢量时工作正常.但是,如果我尝试序列化Foos的映射,它在私有默认构造函数上失败:

std::map<std::string,Foo> f;
f.insert(std::make_pair("hello",Foo(12)));
std::ofstream os("path");
boost::archive::xml_oarchive oa(os);
oa << boost::serialization::make_nvp("f",f);
os.close();
std::map<std::string,Foo> g;
std::ifstream is("path");
boost::archive::xml_iarchive ia(is);
ia >> boost::serialization::make_nvp("f",g);

失败了

In file included from main.cpp:2:
In file included from /usr/local/include/boost/serialization/nvp.hpp:19:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/utility:70:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_pair.h:109:18: error: field of type 'Foo' has private default constructor
      : first(),second() { }
                 ^
/usr/local/include/boost/serialization/access.hpp:132:17: note: in instantiation of member function 'std::pair<const std::basic_string<char>,Foo>::pair' requested here
        ::new(t)T;
                ^
/usr/local/include/boost/serialization/serialization.hpp:93:13: note: in instantiation of function template specialization 'boost::serialization::access::construct<std::pair<const std::basic_string<char>,Foo> >' requested here
    access::construct(t);
            ^
/usr/local/include/boost/serialization/serialization.hpp:158:9: note: in instantiation of function template specialization 'boost::serialization::load_construct_data<boost::archive::xml_iarchive,std::pair<const std::basic_string<char>,Foo> >' requested here
        load_construct_data(ar,t,v);
        ^
/usr/local/include/boost/serialization/detail/stack_constructor.hpp:58:31: note: in instantiation of function template specialization 'boost::serialization::load_construct_data_adl<boost::archive::xml_iarchive,Foo> >' requested here
        boost::serialization::load_construct_data_adl(
                              ^
/usr/local/include/boost/serialization/collections_load_imp.hpp:83:48: note: in instantiation of member function 'boost::serialization::detail::stack_construct<boost::archive::xml_iarchive,Foo> >::stack_construct' requested here
        detail::stack_construct<Archive,type> t(ar,v);
                                               ^
/usr/local/include/boost/serialization/collections_load_imp.hpp:158:16: note: (skipping 12 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
        hint = ifunc(ar,s,item_version,hint);
               ^
/usr/local/include/boost/archive/detail/common_iarchive.hpp:66:18: note: in instantiation of function template specialization 'boost::archive::load<boost::archive::xml_iarchive,std::map<std::basic_string<char>,Foo,std::less<std::basic_string<char> >,std::allocator<std::pair<const std::basic_string<char>,Foo> > > >' requested here
        archive::load(* this->This(),t);
                 ^
/usr/local/include/boost/archive/basic_xml_iarchive.hpp:86:39: note: in instantiation of function template specialization 'boost::archive::detail::common_iarchive<boost::archive::xml_iarchive>::load_override<std::map<std::basic_string<char>,Foo> > > >' requested here
        this->detail_common_iarchive::load_override(t.value(),0);
                                      ^
/usr/local/include/boost/archive/xml_iarchive.hpp:93:38: note: in instantiation of function template specialization 'boost::archive::basic_xml_iarchive<boost::archive::xml_iarchive>::load_override<std::map<std::basic_string<char>,Foo> > > >' requested here
        basic_xml_iarchive<Archive>::load_override(t,0);
                                     ^
/usr/local/include/boost/archive/detail/interface_iarchive.hpp:60:23: note: in instantiation of function template specialization 'boost::archive::xml_iarchive_impl<boost::archive::xml_iarchive>::load_override<const boost::serialization::nvp<std::map<std::basic_string<char>,Foo> > > > >' requested here
        this->This()->load_override(t,0);
                      ^
main.cpp:50:8: note: in instantiation of function template specialization 'boost::archive::detail::interface_iarchive<boost::archive::xml_iarchive>::operator>><const boost::serialization::nvp<std::map<std::basic_string<char>,Foo> > > > >' requested here
    ia >> boost::serialization::make_nvp("f",g);
       ^
main.cpp:34:5: note: implicitly declared private here
    Foo():i(0){}
    ^

我正在使用clang
Ubuntu clang版本3.4-1ubuntu3(标签/ RELEASE_34 / final)(基于LLVM 3.4)

和Ubuntu 14.04LTS一起提供1.55版本.

我试过提供load_construct_data()函数,如下所示:

namespace boost
{
    namespace serialization
    {
        template<class Archive>
        inline void load_construct_data(Archive &archive,Foo*a,unsigned int
file_version)
        {
            ::new(a)Foo(0);
        }
    }
}

但我仍然得到相同的错误,因为它在实例化std :: pair时需要构造函数

解决方法

哦.啊哈.

我刚刚使用Boost 1.57.0将情况与map< string,Foo>进行比较.

嗯,你很幸运.您已经找到了另一个库版本依赖项(可能是一个错误).

>不使用它,但提供私有默认构造函数,GCC 4.8.2编译它就好了:Live On Coliru [1]
> GCC 4.9.0虽然无法编译(它也使用了更新版本的标准库). std :: pair<>默认构造函数无法在那里编译,因为Foo不是默认可构造的:Live On Coliru

幸运的是,使用save_construct_data / load_construct_data的解决方案再次保存了这一天.

但是,您需要满足这样的事实:元素类型实际上不是Foo,而是std :: pair< T const,Foo>.

template <class Archive,typename K> inline friend void save_construct_data(Archive& ar,std::pair<K,Foo> const* v,const unsigned int) {
    std::cerr << __PRETTY_FUNCTION__ << "n";
    ar & boost::serialization::make_nvp("first",v->first);
    ar & boost::serialization::make_nvp("second",v->second.i);
}
template <class Archive,typename K> inline friend void load_construct_data(Archive& ar,Foo>* v,const unsigned int) {
    std::cerr << __PRETTY_FUNCTION__ << "n";
    typename std::remove_cv<K>::type first;
    ar & boost::serialization::make_nvp("first",first);
    int tmp;
    ar & boost::serialization::make_nvp("second",tmp);
    new(v) std::pair<K,Foo>(first,tmp);
}

现在一切正常:

Live On Coliru

#include <boost/serialization/nvp.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/version.hpp>
#include <fstream>
#include <iostream>

class Foo {
    friend class boost::serialization::access;

    template <class Archive> void serialize(Archive &,const unsigned int) {
        std::cerr << __PRETTY_FUNCTION__ << "n";
    }

    template <class Archive,const unsigned int) {
        std::cerr << __PRETTY_FUNCTION__ << "n";
        ar & boost::serialization::make_nvp("first",v->first);
        ar & boost::serialization::make_nvp("second",v->second.i);
    }
    template <class Archive,const unsigned int) {
        std::cerr << __PRETTY_FUNCTION__ << "n";
        typename std::remove_cv<K>::type first;
        ar & boost::serialization::make_nvp("first",first);
        int tmp;
        ar & boost::serialization::make_nvp("second",tmp);
        new(v) std::pair<K,tmp);
    }

    int i;

  public:
    Foo(int k) : i(k) {}

    friend std::ostream& operator<<(std::ostream& os,Foo const& foo) {
        return os << "Foo { " << foo.i << " }";
    }
};

namespace boost { namespace serialization {


} }

int main() {
    using Data = std::map<std::string,Foo>;
    std::cout << "Boost version: " << BOOST_VERSION << "n";

    {
        auto f = Data { {"a",12 },{"b",42} };
        //for (auto& e : f) std::cout << e.first << "," << e.second << "n";
        std::ofstream os("path");
        boost::archive::xml_oarchive oa(os);
        oa << boost::serialization::make_nvp("f",f);
    }

    {
        Data g;
        std::ifstream is("path");
        boost::archive::xml_iarchive ia(is);
        ia >> boost::serialization::make_nvp("f",g);

        for (auto& e : g)
            std::cout << e.first << "," << e.second << "n";
    }
}

哪个印刷品:

Boost version: 105700
void save_construct_data(Archive&,const std::pair<K,Foo>*,unsigned int) [with Archive = boost::archive::xml_oarchive; K = const std::__cxx11::basic_string<char>]
void Foo::serialize(Archive&,unsigned int) [with Archive = boost::archive::xml_oarchive]
void save_construct_data(Archive&,unsigned int) [with Archive = boost::archive::xml_oarchive]
void load_construct_data(Archive&,unsigned int) [with Archive = boost::archive::xml_iarchive; K = const std::__cxx11::basic_string<char>]
void Foo::serialize(Archive&,unsigned int) [with Archive = boost::archive::xml_iarchive]
void load_construct_data(Archive&,unsigned int) [with Archive = boost::archive::xml_iarchive]
a,Foo { 12 }
b,Foo { 42 }

[1](我无法在Coliru上链接它,因为那里的boost库已经重新编译到GCC 5.0 ABI)

笔记

一个更好的,通用的解决方案是对boost :: serialization命名空间中的非默认构造类型一般执行load / save_construct_data技巧.这样,人们就不必“知道”std :: pair<>实施细节.他们可以为自己的用户类型实现load / save_construct_data,JustWork?是将它们放在向量还是映射中.

尽管实现这一点并不简单,但可能会干扰Boost Serialization框架内部的其他一些机制.

我宁愿得到Boost Serialization维护者的一些帮助,以可靠的方式做到这一点.所以,我今天似乎要提交两张票.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读