This commit is contained in:
Johannes Kroll 2015-10-27 23:29:24 +01:00
commit a28e0b1588

View file

@ -240,6 +240,19 @@ struct variant_helper<T, Types...>
variant_helper<Types...>::copy(old_id, old_value, new_value); variant_helper<Types...>::copy(old_id, old_value, new_value);
} }
} }
VARIANT_INLINE static void direct_swap(const std::size_t id, void * lhs, void * rhs)
{
using std::swap; //enable ADL
if (id == sizeof...(Types))
{
// both lhs and rhs hold T
swap(*reinterpret_cast<T*>(lhs), *reinterpret_cast<T*>(rhs));
}
else
{
variant_helper<Types...>::direct_swap(id, lhs, rhs);
}
}
}; };
template<> struct variant_helper<> template<> struct variant_helper<>
@ -247,6 +260,7 @@ template<> struct variant_helper<>
VARIANT_INLINE static void destroy(const std::size_t, void *) {} VARIANT_INLINE static void destroy(const std::size_t, void *) {}
VARIANT_INLINE static void move(const std::size_t, void *, void *) {} VARIANT_INLINE static void move(const std::size_t, void *, void *) {}
VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {} VARIANT_INLINE static void copy(const std::size_t, const void *, void *) {}
VARIANT_INLINE static void direct_swap(const std::size_t, void *, void *) {}
}; };
namespace detail { namespace detail {
@ -274,7 +288,7 @@ struct unwrapper<recursive_wrapper<T>>
{ {
return obj.get(); return obj.get();
} }
auto operator() (recursive_wrapper<T> & obj) const auto operator() (recursive_wrapper<T> & obj) const
-> typename recursive_wrapper<T>::type & -> typename recursive_wrapper<T>::type &
{ {
@ -595,16 +609,24 @@ public:
helper_type::move(old.type_index, &old.data, &data); helper_type::move(old.type_index, &old.data, &data);
} }
friend void swap(variant<Types...> & first, variant<Types...> & second) void assign(variant<Types...> & rhs)
{ {
using std::swap; //enable ADL if (type_index == rhs.type_index)
swap(first.type_index, second.type_index); {
swap(first.data, second.data); helper_type::direct_swap(rhs.type_index, &rhs.data, &data);
}
else
{
helper_type::destroy(type_index, &data);
type_index = detail::invalid_value;
helper_type::copy(rhs.type_index, &rhs.data, &data);
type_index = rhs.type_index;
}
} }
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> other) VARIANT_INLINE variant<Types...>& operator=(variant<Types...> other)
{ {
swap(*this, other); assign(other);
return *this; return *this;
} }
@ -614,7 +636,7 @@ public:
VARIANT_INLINE variant<Types...>& operator=(T && rhs) noexcept VARIANT_INLINE variant<Types...>& operator=(T && rhs) noexcept
{ {
variant<Types...> temp(std::forward<T>(rhs)); variant<Types...> temp(std::forward<T>(rhs));
swap(*this, temp); assign(temp);
return *this; return *this;
} }
@ -623,7 +645,7 @@ public:
VARIANT_INLINE variant<Types...>& operator=(T const& rhs) VARIANT_INLINE variant<Types...>& operator=(T const& rhs)
{ {
variant<Types...> temp(rhs); variant<Types...> temp(rhs);
swap(*this, temp); assign(temp);
return *this; return *this;
} }