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