diff --git a/include/boost/serialization/std_variant.hpp b/include/boost/serialization/std_variant.hpp index c02309b48..2a847deda 100644 --- a/include/boost/serialization/std_variant.hpp +++ b/include/boost/serialization/std_variant.hpp @@ -122,11 +122,17 @@ struct variant_impl // with an implementation that de-serialized to the address of the // aligned storage included in the variant. using type = mp::front; - type value; - ar >> BOOST_SERIALIZATION_NVP(value); - v = std::move(value); + struct ValueData { + alignas(type) unsigned char data[sizeof(type)]; + type * ptr() { return reinterpret_cast(data); } + ValueData() { access::construct(ptr()); } + ~ValueData() { ptr()->~type(); } + } value; + + ar >> BOOST_SERIALIZATION_NVP(*value.ptr()); + v = std::move(*value.ptr()); type * new_address = & std::get(v); - ar.reset_object_address(new_address, & value); + ar.reset_object_address(new_address, value.ptr()); return; } //typedef typename mpl::pop_front::type type; diff --git a/include/boost/serialization/variant.hpp b/include/boost/serialization/variant.hpp index b888a5941..5b7f97902 100644 --- a/include/boost/serialization/variant.hpp +++ b/include/boost/serialization/variant.hpp @@ -159,11 +159,17 @@ struct variant_impl { // with an implementation that de-serialized to the address of the // aligned storage included in the variant. typedef typename mpl::front::type head_type; - head_type value; - ar >> BOOST_SERIALIZATION_NVP(value); - v = std::move(value);; + struct ValueData { + alignas(head_type) unsigned char data[sizeof(head_type)]; + head_type * ptr() { return reinterpret_cast(data); } + ValueData() { access::construct(ptr()); } + ~ValueData() { ptr()->~head_type(); } + } value; + + ar >> BOOST_SERIALIZATION_NVP(*value.ptr()); + v = std::move(*value.ptr()); head_type * new_address = & get(v); - ar.reset_object_address(new_address, & value); + ar.reset_object_address(new_address, value.ptr()); return; } typedef typename mpl::pop_front::type type; diff --git a/include/boost/serialization/variant2.hpp b/include/boost/serialization/variant2.hpp index 7f8fcbde3..c26768fa0 100644 --- a/include/boost/serialization/variant2.hpp +++ b/include/boost/serialization/variant2.hpp @@ -92,11 +92,17 @@ struct variant_impl // with an implementation that de-serialized to the address of the // aligned storage included in the variant. using type = mp11::mp_front; - type value; - ar >> BOOST_SERIALIZATION_NVP(value); - v = std::move(value); + struct ValueData { + alignas(type) unsigned char data[sizeof(type)]; + type * ptr() { return reinterpret_cast(data); } + ValueData() { access::construct(ptr()); } + ~ValueData() { ptr()->~type(); } + } value; + + ar >> BOOST_SERIALIZATION_NVP(*value.ptr()); + v = std::move(*value.ptr()); type * new_address = & variant2::get(v); - ar.reset_object_address(new_address, & value); + ar.reset_object_address(new_address, value.ptr()); return; } //typedef typename mpl::pop_front::type type; diff --git a/test/test_variant.cpp b/test/test_variant.cpp index 3de1afd33..ab9a13e52 100644 --- a/test/test_variant.cpp +++ b/test/test_variant.cpp @@ -57,6 +57,32 @@ namespace boost { #include "A.hpp" #include "A.ipp" +class V { +private: + friend class boost::serialization::access; + int m_i; + V() : + m_i(0) + {} + template + void serialize(Archive& ar, unsigned /*version*/) + { + ar & BOOST_SERIALIZATION_NVP(m_i); + } +public: + V(int i) : + m_i(i) + {} + int get_i() const + { + return m_i; + } + bool operator==(const V& other) const + { + return m_i == other.m_i; + } +}; + class are_equal : public boost::static_visitor { @@ -156,6 +182,8 @@ void test(Variant & v) test_type(v); v = std::string("we can't stop here, this is Bat Country"); test_type(v); + v = V(67); + test_type(v); } #include @@ -166,10 +194,10 @@ void test(Variant & v) int test_boost_variant(){ std::cerr << "Testing boost_variant\n"; - boost::variant v; + boost::variant v; test(v); const A a; - boost::variant v1 = & a; + boost::variant v1 = & a; test_type(v1); return EXIT_SUCCESS; } @@ -180,10 +208,10 @@ int test_boost_variant(){ int test_boost_variant2(){ std::cerr << "Testing boost_variant2\n"; - boost::variant2::variant v; + boost::variant2::variant v; test(v); const A a; - boost::variant2::variant v1 = & a; + boost::variant2::variant v1 = & a; test_type(v1); return EXIT_SUCCESS; } @@ -194,10 +222,10 @@ int test_boost_variant2(){ #include int test_std_variant(){ std::cerr << "Testing Std Variant\n"; - std::variant v; + std::variant v; test(v); const A a; - std::variant v1 = & a; + std::variant v1 = & a; test_type(v1); return EXIT_SUCCESS; }