Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/boost/serialization/access.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ class access {
// class doesn't have a class-specific placement new defined.
::new(t)T;
}
template<class T>
static T *construct_r(void * t) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, had to add a new overload of construct that actually returned the placement-new result, because of pointer provenance issues.

alignas(T) unsigned char mem[sizeof(T)];
T *ptr = reinterpret_cast<T*>(mem);
::new(ptr)T;

ptr->stuff();

Apparently is no bueno because the compiler can assume that ptr is NOT the same thing as the in-place-constructed T. Need to instead do something like

alignas(T) unsigned char mem[sizeof(T)];
T *ptr = ::new(mem)T;

ptr->stuff();

return ::new(t)T;
}
template<class T, class U>
static T & cast_reference(U & u){
return static_cast<T &>(u);
Expand Down
20 changes: 14 additions & 6 deletions include/boost/serialization/std_variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,19 @@ struct variant_impl
// with an implementation that de-serialized to the address of the
// aligned storage included in the variant.
using type = mp::front<Seq>;
type value;
ar >> BOOST_SERIALIZATION_NVP(value);
v = std::move(value);
struct ValueData {
alignas(type) unsigned char data[sizeof(type)];
type *ptr_;
void * mem() { return static_cast<void *>(data); }
type * ptr() { return ptr_; }
ValueData() : ptr_(access::construct_r<type>(mem())) {}
~ValueData() { ptr()->~type(); }
} value;

ar >> BOOST_SERIALIZATION_NVP(*value.ptr());
v = std::move(*value.ptr());
type * new_address = & std::get<type>(v);
ar.reset_object_address(new_address, & value);
ar.reset_object_address(new_address, value.ptr());
return;
}
//typedef typename mpl::pop_front<S>::type type;
Expand All @@ -149,7 +157,7 @@ struct variant_impl<0, Seq>

template<class Archive, class... Types>
void load(
Archive & ar,
Archive & ar,
std::variant<Types...>& v,
const unsigned int version
){
Expand Down Expand Up @@ -188,7 +196,7 @@ void serialize(Archive &, std::monostate &, const unsigned int /*version*/)

namespace boost {
namespace serialization {

template<class... Types>
struct tracking_level<
std::variant<Types...>
Expand Down
16 changes: 12 additions & 4 deletions include/boost/serialization/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,19 @@ struct variant_impl {
// with an implementation that de-serialized to the address of the
// aligned storage included in the variant.
typedef typename mpl::front<S>::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_;
void * mem() { return static_cast<void *>(data); }
head_type * ptr() { return ptr_; }
ValueData() : ptr_(access::construct_r<head_type>(mem())) {}
~ValueData() { ptr()->~head_type(); }
} value;

ar >> BOOST_SERIALIZATION_NVP(*value.ptr());
v = std::move(*value.ptr());
head_type * new_address = & get<head_type>(v);
ar.reset_object_address(new_address, & value);
ar.reset_object_address(new_address, value.ptr());
return;
}
typedef typename mpl::pop_front<S>::type type;
Expand Down
20 changes: 14 additions & 6 deletions include/boost/serialization/variant2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,19 @@ 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<Seq>;
type value;
ar >> BOOST_SERIALIZATION_NVP(value);
v = std::move(value);
struct ValueData {
alignas(type) unsigned char data[sizeof(type)];
type *ptr_;
void * mem() { return static_cast<void *>(data); }
type * ptr() { return ptr_; }
ValueData() : ptr_(access::construct_r<type>(mem())) {}
~ValueData() { ptr()->~type(); }
} value;

ar >> BOOST_SERIALIZATION_NVP(*value.ptr());
v = std::move(*value.ptr());
type * new_address = & variant2::get<type>(v);
ar.reset_object_address(new_address, & value);
ar.reset_object_address(new_address, value.ptr());
return;
}
//typedef typename mpl::pop_front<S>::type type;
Expand All @@ -119,7 +127,7 @@ struct variant_impl<Seq>

template<class Archive, class... Types>
void load(
Archive & ar,
Archive & ar,
variant2::variant<Types...> & v,
const unsigned int version
){
Expand Down Expand Up @@ -158,7 +166,7 @@ void serialize(Archive &ar, variant2::monostate &, const unsigned int /*version*

namespace boost {
namespace serialization {

template<class... Types>
struct tracking_level<
variant2::variant<Types...>
Expand Down
40 changes: 34 additions & 6 deletions test/test_variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<class Archive>
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<bool>
{
Expand Down Expand Up @@ -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 <boost/serialization/variant.hpp>
Expand All @@ -166,10 +194,10 @@ void test(Variant & v)

int test_boost_variant(){
std::cerr << "Testing boost_variant\n";
boost::variant<bool, int, float, double, A, std::string> v;
boost::variant<bool, int, float, double, A, std::string, V> v;
test(v);
const A a;
boost::variant<bool, int, float, double, const A *, std::string> v1 = & a;
boost::variant<bool, int, float, double, const A *, std::string, V> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
Expand All @@ -180,10 +208,10 @@ int test_boost_variant(){

int test_boost_variant2(){
std::cerr << "Testing boost_variant2\n";
boost::variant2::variant<bool, int, float, double, A, std::string> v;
boost::variant2::variant<bool, int, float, double, A, std::string, V> v;
test(v);
const A a;
boost::variant2::variant<bool, int, float, double, const A *, std::string> v1 = & a;
boost::variant2::variant<bool, int, float, double, const A *, std::string, V> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
Expand All @@ -194,10 +222,10 @@ int test_boost_variant2(){
#include <variant>
int test_std_variant(){
std::cerr << "Testing Std Variant\n";
std::variant<bool, int, float, double, A, std::string> v;
std::variant<bool, int, float, double, A, std::string, V> v;
test(v);
const A a;
std::variant<bool, int, float, double, const A *, std::string> v1 = & a;
std::variant<bool, int, float, double, const A *, std::string, V> v1 = & a;
test_type(v1);
return EXIT_SUCCESS;
}
Expand Down