diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 100088724..01db3a807 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -240,6 +240,19 @@ struct variant_helper variant_helper::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(lhs), *reinterpret_cast(rhs)); + } + else + { + variant_helper::direct_swap(id, lhs, rhs); + } + } }; 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 move(const std::size_t, 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 { @@ -274,7 +288,7 @@ struct unwrapper> { return obj.get(); } - + auto operator() (recursive_wrapper & obj) const -> typename recursive_wrapper::type & { @@ -595,16 +609,24 @@ public: helper_type::move(old.type_index, &old.data, &data); } - friend void swap(variant & first, variant & second) + void assign(variant & rhs) { - using std::swap; //enable ADL - swap(first.type_index, second.type_index); - swap(first.data, second.data); + if (type_index == rhs.type_index) + { + 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& operator=(variant other) { - swap(*this, other); + assign(other); return *this; } @@ -614,7 +636,7 @@ public: VARIANT_INLINE variant& operator=(T && rhs) noexcept { variant temp(std::forward(rhs)); - swap(*this, temp); + assign(temp); return *this; } @@ -623,7 +645,7 @@ public: VARIANT_INLINE variant& operator=(T const& rhs) { variant temp(rhs); - swap(*this, temp); + assign(temp); return *this; }