From d255829bbc233d4d60bcf05b36319307dfba4a30 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Wed, 15 Feb 2017 09:01:06 +0000 Subject: [PATCH] re PR libstdc++/78723 ([variant] P0393r3: "Making variant greater equal again" is unimplemented) PR libstdc++/78723 * include/std/variant (operator<(), operator>(), operator<=(), operator>=(), operator==(), operator!=()): Implement P0393R3. * testsuite/20_util/variant/compile.cc: Adjust tests. * testsuite/20_util/variant/run.cc: Adjust tests. From-SVN: r245475 --- libstdc++-v3/ChangeLog | 8 + libstdc++-v3/include/std/variant | 187 +++++++----------- .../testsuite/20_util/variant/compile.cc | 4 + libstdc++-v3/testsuite/20_util/variant/run.cc | 24 +++ 4 files changed, 108 insertions(+), 115 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ec6e601c1ef..5ce466fa9ec 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2017-02-15 Tim Shen + + PR libstdc++/78723 + * include/std/variant (operator<(), operator>(), operator<=(), + operator>=(), operator==(), operator!=()): Implement P0393R3. + * testsuite/20_util/variant/compile.cc: Adjust tests. + * testsuite/20_util/variant/run.cc: Adjust tests. + 2017-02-15 Tim Shen PR libstdc++/79513 diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 866c4c40a61..0cc50d03c4d 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -264,21 +264,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(__ref_cast<_Lhs>(__lhs), __ref_cast<_Rhs>(__rhs)); } - template - constexpr bool - __erased_equal_to(_Variant&& __lhs, _Variant&& __rhs) - { - return __get<_Np>(std::forward<_Variant>(__lhs)) - == __get<_Np>(std::forward<_Variant>(__rhs)); +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + constexpr bool \ + __erased_##__NAME(const _Variant& __lhs, const _Variant& __rhs) \ + { \ + return __get<_Np>(std::forward<_Variant>(__lhs)) \ + __OP __get<_Np>(std::forward<_Variant>(__rhs)); \ } - template - constexpr bool - __erased_less_than(const _Variant& __lhs, const _Variant& __rhs) - { - return __get<_Np>(std::forward<_Variant>(__lhs)) - < __get<_Np>(std::forward<_Variant>(__rhs)); - } + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE template constexpr size_t @@ -813,63 +815,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(__ptr); } - template - constexpr bool operator==(const variant<_Types...>& __lhs, - const variant<_Types...>& __rhs) - { - return __lhs._M_equal_to(__rhs, std::index_sequence_for<_Types...>{}); - } - - template - constexpr inline bool - operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs == __rhs); } - - template - constexpr inline bool - operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { - return __lhs._M_less_than(__rhs, std::index_sequence_for<_Types...>{}); - } - - template - constexpr inline bool - operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return __rhs < __lhs; } - - template - constexpr inline bool - operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs > __rhs); } + struct monostate { }; - template - constexpr inline bool - operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs < __rhs); } +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + constexpr bool operator __OP(const variant<_Types...>& __lhs, \ + const variant<_Types...>& __rhs) \ + { \ + return __lhs._M_##__NAME(__rhs, std::index_sequence_for<_Types...>{}); \ + } \ +\ + constexpr bool operator __OP(monostate, monostate) noexcept \ + { return 0 __OP 0; } + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE template constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); - struct monostate { }; - - constexpr bool operator<(monostate, monostate) noexcept - { return false; } - - constexpr bool operator>(monostate, monostate) noexcept - { return false; } - - constexpr bool operator<=(monostate, monostate) noexcept - { return true; } - - constexpr bool operator>=(monostate, monostate) noexcept - { return true; } - - constexpr bool operator==(monostate, monostate) noexcept - { return true; } - - constexpr bool operator!=(monostate, monostate) noexcept - { return false; } - template inline enable_if_t<(is_move_constructible_v<_Types> && ...) && (is_swappable_v<_Types> && ...)> @@ -1140,51 +1110,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: - template - static constexpr bool - (*_S_equal_to_vtable[])(const variant&, const variant&) = - { &__detail::__variant::__erased_equal_to< - const variant&, __indices>... }; - - template - static constexpr bool - (*_S_less_than_vtable[])(const variant&, const variant&) = - { &__detail::__variant::__erased_less_than< - const variant&, __indices>... }; - - template - constexpr bool - _M_equal_to(const variant& __rhs, - std::index_sequence<__indices...>) const - { - if (this->index() != __rhs.index()) - return false; - - if (this->valueless_by_exception()) - return true; - - return _S_equal_to_vtable<__indices...>[this->index()](*this, __rhs); +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + static constexpr bool \ + (*_S_erased_##__NAME[])(const variant&, const variant&) = \ + { &__detail::__variant::__erased_##__NAME< \ + const variant&, __indices>... }; \ + template \ + constexpr inline bool \ + _M_##__NAME(const variant& __rhs, \ + std::index_sequence<__indices...>) const \ + { \ + auto __lhs_index = this->index(); \ + auto __rhs_index = __rhs.index(); \ + if (__lhs_index != __rhs_index || valueless_by_exception()) \ + /* Modulo addition. */ \ + return __lhs_index + 1 __OP __rhs_index + 1; \ + return _S_erased_##__NAME<__indices...>[__lhs_index](*this, __rhs); \ } - template - constexpr inline bool - _M_less_than(const variant& __rhs, - std::index_sequence<__indices...>) const - { - auto __lhs_index = this->index(); - auto __rhs_index = __rhs.index(); + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) - if (__lhs_index < __rhs_index) - return true; - - if (__lhs_index > __rhs_index) - return false; - - if (this->valueless_by_exception()) - return false; - - return _S_less_than_vtable<__indices...>[__lhs_index](*this, __rhs); - } +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE template friend constexpr decltype(auto) __detail::__variant:: @@ -1200,15 +1152,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif __get_storage(_Vp&& __v); - template - friend constexpr bool - operator==(const variant<_Tp...>& __lhs, - const variant<_Tp...>& __rhs); +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ + template \ + friend constexpr bool \ + operator __OP(const variant<_Tp...>& __lhs, \ + const variant<_Tp...>& __rhs); + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>) - template - friend constexpr bool - operator<(const variant<_Tp...>& __lhs, - const variant<_Tp...>& __rhs); +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE }; template diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc b/libstdc++-v3/testsuite/20_util/variant/compile.cc index 3bf9d5bfba3..06e8eb31ee8 100644 --- a/libstdc++-v3/testsuite/20_util/variant/compile.cc +++ b/libstdc++-v3/testsuite/20_util/variant/compile.cc @@ -65,7 +65,11 @@ struct nonliteral nonliteral() { } bool operator<(const nonliteral&) const; + bool operator<=(const nonliteral&) const; bool operator==(const nonliteral&) const; + bool operator!=(const nonliteral&) const; + bool operator>=(const nonliteral&) const; + bool operator>(const nonliteral&) const; }; void default_ctor() diff --git a/libstdc++-v3/testsuite/20_util/variant/run.cc b/libstdc++-v3/testsuite/20_util/variant/run.cc index 121fd22527d..db4529eea3f 100644 --- a/libstdc++-v3/testsuite/20_util/variant/run.cc +++ b/libstdc++-v3/testsuite/20_util/variant/run.cc @@ -47,6 +47,13 @@ struct AlwaysThrow throw nullptr; return *this; } + + bool operator<(const AlwaysThrow&) const { VERIFY(false); } + bool operator<=(const AlwaysThrow&) const { VERIFY(false); } + bool operator==(const AlwaysThrow&) const { VERIFY(false); } + bool operator!=(const AlwaysThrow&) const { VERIFY(false); } + bool operator>=(const AlwaysThrow&) const { VERIFY(false); } + bool operator>(const AlwaysThrow&) const { VERIFY(false); } }; void default_ctor() @@ -229,6 +236,23 @@ void test_relational() VERIFY((variant(2) < variant("a"))); VERIFY((variant(2) > variant("a"))); + + { + variant v, w; + try + { + AlwaysThrow a; + v = a; + } + catch (nullptr_t) { } + VERIFY(v.valueless_by_exception()); + VERIFY(v < w); + VERIFY(v <= w); + VERIFY(!(v == w)); + VERIFY(v != w); + VERIFY(w > v); + VERIFY(w >= v); + } } void test_swap() -- 2.30.2