c – boost :: serialization:具有私有默认构造函数的对象在向
请考虑以下代码:
#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 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] 解 幸运的是,使用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维护者的一些帮助,以可靠的方式做到这一点.所以,我今天似乎要提交两张票. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |