[v3 PATCH] Use single-visitation in variant assignment and swap.
Jonathan Wakely
jwakely@redhat.com
Mon Apr 1 11:55:00 GMT 2019
On 01/04/19 11:45 +0300, Ville Voutilainen wrote:
>@@ -570,45 +574,44 @@ namespace __variant
> operator=(const _Copy_assign_base& __rhs)
> noexcept(_Traits<_Types...>::_S_nothrow_copy_assign)
> {
>- __do_visit([this, &__rhs](auto&& __this_mem, auto&& __rhs_mem) mutable
>- -> __detail::__variant::__variant_cookie
>+ __do_visit<__visit_with_index>([this](auto&& __rhs_mem,
>+ auto __rhs_index) mutable
>+ -> __detail::__variant::__variant_idx_cookie
> {
>- if constexpr (is_same_v<
>- remove_reference_t<decltype(__this_mem)>,
>- remove_reference_t<decltype(__rhs_mem)>>)
>+ if constexpr (__rhs_index != variant_npos)
> {
>- if constexpr (!is_same_v<
>- remove_reference_t<decltype(__rhs_mem)>,
>- __variant_cookie>)
>- __this_mem = __rhs_mem;
>- }
>- else
>- {
>- if constexpr (!is_same_v<
>- remove_reference_t<decltype(__rhs_mem)>,
>- __variant_cookie>)
>+ if (this->_M_index == __rhs_index)
> {
>- using __rhs_type =
>- remove_reference_t<decltype(__rhs_mem)>;
>- if constexpr (is_nothrow_copy_constructible_v<__rhs_type>
>- || !is_nothrow_move_constructible_v<__rhs_type>)
>+ if constexpr (__rhs_index != variant_npos)
> {
>- this->_M_destructive_copy(__rhs._M_index, __rhs_mem);
>+ auto& __this_mem =
>+ __get<__rhs_index>(*this);
Qualify this as __variant::__get please.
>+ if constexpr (is_same_v<
>+ remove_reference_t<decltype(__this_mem)>,
>+ remove_reference_t<decltype(__rhs_mem)>>)
>+ __this_mem = __rhs_mem;
> }
>+ }
>+ else
>+ {
>+ using __rhs_type =
>+ remove_reference_t<decltype(__rhs_mem)>;
>+ if constexpr
>+ (is_nothrow_copy_constructible_v<__rhs_type>
>+ || !is_nothrow_move_constructible_v<__rhs_type>)
>+ this->_M_destructive_copy(__rhs_index, __rhs_mem);
> else
> {
> auto __tmp(__rhs_mem);
>- this->_M_destructive_move(__rhs._M_index,
>+ this->_M_destructive_move(__rhs_index,
> std::move(__tmp));
> }
> }
>- else
>- {
>- this->_M_reset();
>- }
> }
>- return {};
>- }, __variant_cast<_Types...>(*this), __variant_cast<_Types...>(__rhs));
>+ else
>+ this->_M_reset();
>+ return {};
>+ }, __variant_cast<_Types...>(__rhs));
> __glibcxx_assert(this->_M_index == __rhs._M_index);
> return *this;
> }
>@@ -641,25 +644,32 @@ namespace __variant
> operator=(_Move_assign_base&& __rhs)
> noexcept(_Traits<_Types...>::_S_nothrow_move_assign)
> {
>- __do_visit([this, &__rhs](auto&& __this_mem, auto&& __rhs_mem) mutable
>- -> __detail::__variant::__variant_cookie
>+ __do_visit<__visit_with_index>([this](auto&& __rhs_mem,
>+ auto __rhs_index) mutable
>+ -> __detail::__variant::__variant_idx_cookie
> {
>- if constexpr (is_same_v<
>- remove_reference_t<decltype(__this_mem)>,
>- remove_reference_t<decltype(__rhs_mem)>>)
>+ if constexpr (__rhs_index != variant_npos)
> {
>- if constexpr (!is_same_v<
>- remove_reference_t<decltype(__rhs_mem)>,
>- __variant_cookie>)
>- __this_mem = std::move(__rhs_mem);
>+ if (this->_M_index == __rhs_index)
>+ {
>+ if constexpr (__rhs_index != variant_npos)
>+ {
>+ auto& __this_mem =
>+ __get<__rhs_index>(*this);
And here.
>+ if constexpr (is_same_v<
>+ remove_reference_t<decltype(__this_mem)>,
>+ remove_reference_t<decltype(__rhs_mem)>>)
>+ __this_mem = std::move(__rhs_mem);
>+ }
>+ }
>+ else
>+ this->_M_destructive_move(__rhs_index,
>+ std::move(__rhs_mem));
> }
> else
>- {
>- auto __tmp(std::move(__rhs_mem));
>- this->_M_destructive_move(__rhs._M_index, std::move(__tmp));
>- }
>- return {};
>- }, __variant_cast<_Types...>(*this), __variant_cast<_Types...>(__rhs));
>+ this->_M_reset();
>+ return {};
>+ }, __variant_cast<_Types...>(__rhs));
> __glibcxx_assert(this->_M_index == __rhs._M_index);
> return *this;
> }
>@@ -1082,25 +1099,25 @@ namespace __variant
> const variant<_Types...>& __rhs) \
> { \
> bool __ret = true; \
>- __do_visit([&__ret, &__lhs, __rhs] \
>- (auto&& __this_mem, auto&& __rhs_mem) mutable \
>- -> __detail::__variant::__variant_cookie \
>+ __do_visit<__detail::__variant::__visit_with_index>( \
>+ [&__ret, &__lhs, __rhs] \
>+ (auto&& __rhs_mem, auto __rhs_index) mutable \
>+ -> __detail::__variant::__variant_idx_cookie \
> { \
>- if constexpr (!is_same_v< \
>- remove_reference_t<decltype(__this_mem)>, \
>- remove_reference_t<decltype(__rhs_mem)>> \
>- || is_same_v<decltype(__this_mem), \
>- __detail::__variant::__variant_cookie>) \
>- __ret = (__lhs.index() + 1) __OP (__rhs.index() + 1); \
>- else if constexpr (is_same_v< \
>- remove_reference_t<decltype(__this_mem)>, \
>- remove_reference_t<decltype(__rhs_mem)>> \
>- && !is_same_v< \
>- remove_reference_t<decltype(__this_mem)>, \
>- __detail::__variant::__variant_cookie>) \
>- __ret = __this_mem __OP __rhs_mem; \
>+ if constexpr (__rhs_index != variant_npos) \
>+ { \
>+ if (__lhs.index() == __rhs_index) \
>+ { \
>+ auto& __this_mem = get<__rhs_index>(__lhs); \
And std::get here.
>+ __ret = __this_mem __OP __rhs_mem; \
>+ } \
>+ else \
>+ __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
>+ } \
>+ else \
>+ __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
> return {}; \
>- }, __lhs, __rhs); \
>+ }, __rhs); \
> return __ret; \
> } \
> \
>@@ -1402,51 +1419,47 @@ namespace __variant
> noexcept((__is_nothrow_swappable<_Types>::value && ...)
> && is_nothrow_move_constructible_v<variant>)
> {
>- __do_visit([this, &__rhs](auto&& __this_mem, auto&& __rhs_mem) mutable
>- -> __detail::__variant::__variant_cookie
>+ __do_visit<__detail::__variant::__visit_with_index>(
>+ [this, &__rhs](auto&& __rhs_mem,
>+ auto __rhs_index) mutable
>+ -> __detail::__variant::__variant_idx_cookie
> {
>- if constexpr (is_same_v<
>- remove_reference_t<decltype(__this_mem)>,
>- remove_reference_t<decltype(__rhs_mem)>>)
>+ if constexpr (__rhs_index != variant_npos)
> {
>- if constexpr (!is_same_v<
>- remove_reference_t<decltype(__rhs_mem)>,
>- __detail::__variant::__variant_cookie>)
>+ if (this->index() == __rhs_index)
> {
>+ auto& __this_mem =
>+ get<__rhs_index>(*this);
And here.
OK with those four qualifications, thanks very much.
More information about the Libstdc++
mailing list