#12321 closed Bugs (fixed)
save for boost::optional doesn't call save_construct_data but load calls load_construct_data
Reported by: | Owned by: | Robert Ramey | |
---|---|---|---|
Milestone: | To Be Determined | Component: | serialization |
Version: | Boost 1.61.0 | Severity: | Problem |
Keywords: | Cc: |
Description
$ cat main.cpp
#include <stdexcept> #include <iostream> #include <sstream> #include <boost/optional.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/optional.hpp> struct Foo { Foo(int aBar) : mBar(aBar) { if (mBar > 10) { throw std::logic_error("too big bar"); } } int bar() const { return mBar; } private: int mBar; }; namespace boost { namespace serialization { template<class Archive> inline void serialize(Archive & ar, Foo& foo, const unsigned int /*version*/) { std::cout << __FUNCTION__ << " called" << std::endl; } template<class Archive> inline void save_construct_data(Archive & ar, const Foo* foo, const unsigned int /*version*/) { std::cout << __FUNCTION__ << " called" << std::endl; ar << foo->bar(); } template<class Archive> inline void load_construct_data(Archive & ar, Foo* foo, const unsigned int /*version*/) { std::cout << __FUNCTION__ << " called" << std::endl; int bar; ar >> bar; ::new(foo) Foo(bar); } } // serialization } // boost int main() { boost::optional<Foo> oldFoo = Foo(10); std::ostringstream outStream; boost::archive::text_oarchive outArchive(outStream); outArchive & oldFoo; boost::optional<Foo> newFoo; std::istringstream inStream(outStream.str()); boost::archive::text_iarchive inArchive(inStream); inArchive & newFoo; }
$ clang++ -I include -L lib -l boost_serialization --std=c++11 main.cpp
$ LD_LIBRARY_PATH=lib ./a.out serialize called load_construct_data called terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): input stream error
Aborted (core dumped)
Change History (4)
comment:1 by , 6 years ago
comment:3 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I believe I have fixed this in a definitive way. I've checked it in to the develop branch. This is too late for boost 1.63 but will come out in next release
comment:4 by , 6 years ago
I had fixed your example and checked it in. But upon doing more testing I concluded that my "fix" would just break something else. Spending a lot more time on this convinced me that the root cause of the problem is the serialization of a type which out a default constructor. The library as currently constituted really can't do that - this is not due to the usage of "optional" it's a general limitation. Maybe if I made the library again I might address this limitation. Or maybe I tried originally but just accepted the limitation (without documenting it). So I'm going to make a few changes.
a) fix it (again!) so that the test works. This will make your case fail
b) update the documentation to clarify this point. There is a workaround. If a class has no default constructor it CAN be serialized through a pointer while overloading save/load construct data.
c) use the boost type trait "has_default_constructor" to trap violations of tis rule and point to an explanation.
Sorry you'll have to work around this.
Robert Ramey
I unfortunately ran into the same issue. When only serializing pointers the issue can be work arounded.