[Boost-bugs] [Boost C++ Libraries] #11342: Vector serialization with non-default-constructible element type fails to compile

Subject: [Boost-bugs] [Boost C++ Libraries] #11342: Vector serialization with non-default-constructible element type fails to compile
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-05-25 23:47:11


#11342: Vector serialization with non-default-constructible element type fails to
compile
------------------------------+---------------------------
 Reporter: bugs@… | Owner: ramey
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: serialization
  Version: Boost 1.58.0 | Severity: Regression
 Keywords: |
------------------------------+---------------------------
 The following sample compiles in Boost 1.57.0 but doesn't in Boost 1.58.0:


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

 The problem is a new piece of code that tries to switch on
 `is_default_constructible<T>` ***at compile time***. That can't work:
 (from serialization/vector.hpp in the unoptimized version of load(...)):

 {{{
 if(detail::is_default_constructible<U>()){
     t.resize(count);
     // ... snip ...
 }
 else{
     t.reserve(count);
     // ... snip ...
 }
 }}}

 Instead of having the branches in the same flow code, it should be
 dispatched so that only the applicable branch is instantiated. I tested
 with this simplistic approach:

 {{{
 namespace sehe_bugfix {
     template<class Archive, class U, class Allocator>
     inline void load_elements(
         Archive & ar,
         std::vector<U, Allocator> &t,
         const unsigned int /* file_version */,
         collection_size_type count,
         mpl::true_
     ){
         const boost::archive::library_version_type library_version(
             ar.get_library_version()
         );
         item_version_type item_version(0);
         if(boost::archive::library_version_type(3) < library_version){
             ar >> BOOST_SERIALIZATION_NVP(item_version);
         }
         t.resize(count);
         typename std::vector<U, Allocator>::iterator hint;
         hint = t.begin();
         while(count-- > 0){
             ar >> boost::serialization::make_nvp("item", *hint++);
         }
     }

     template<class Archive, class U, class Allocator>
     inline void load_elements(
         Archive & ar,
         std::vector<U, Allocator> &t,
         const unsigned int /* file_version */,
         collection_size_type count,
         mpl::false_
     ){
         const boost::archive::library_version_type library_version(
             ar.get_library_version()
         );
         item_version_type item_version(0);
         if(boost::archive::library_version_type(3) < library_version){
             ar >> BOOST_SERIALIZATION_NVP(item_version);
         }
         t.reserve(count);
         while(count-- > 0){
             detail::stack_construct<Archive, U> u(ar, item_version);
             ar >> boost::serialization::make_nvp("item", u.reference());
             t.push_back(u.reference());
             ar.reset_object_address(& t.back() , & u.reference());
         }
     }
 }

 template<class Archive, class U, class Allocator>
 inline void load(
     Archive & ar,
     std::vector<U, Allocator> &t,
     const unsigned int file_version,
     mpl::false_
 ){
     const boost::archive::library_version_type library_version(
         ar.get_library_version()
     );
     // retrieve number of elements
     item_version_type item_version(0);
     collection_size_type count;
     ar >> BOOST_SERIALIZATION_NVP(count);

     sehe_bugfix::load_elements(ar, t, file_version, count,
 detail::is_default_constructible<U>());
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/11342>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:18 UTC