On Tue, Jan 3, 2017 at 6:17 AM, Jonathan Wakely <jwak...@redhat.com> wrote: > On 01/01/17 04:17 -0800, Tim Shen via libstdc++ wrote: >> >> +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __name) \ >> + template<typename... _Types> \ >> + 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(<, _erased_less_than) >> + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, _erased_less_equal) >> + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, _erased_equal) >> + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, _erased_not_equal) >> + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, _erased_greater_than) >> + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, _erased_greater) > > > These need double underscore prefixes.
Done. > > Still reviewing the rest ... > -- Regards, Tim Shen
commit fba8c3c8cca773a501766aff90b13f72e42d9355 Author: Tim Shen <tims...@google.com> Date: Sun Jan 1 04:07:15 2017 -0800 2017-01-01 Tim Shen <tims...@google.com> PR libstdc++/78723 * include/std/variant: Implement P0393R3. * testsuite/20_util/variant/compile.cc: Adjust tests. * testsuite/20_util/variant/run.cc: Adjust tests. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 3d025a7..9ca61d6 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -263,21 +263,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(__ref_cast<_Lhs>(__lhs), __ref_cast<_Rhs>(__rhs)); } - template<typename _Variant, size_t _Np> - 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, __function_name) \ + template<typename _Variant, size_t _Np> \ + constexpr bool \ + __function_name(const _Variant& __lhs, const _Variant& __rhs) \ + { \ + return __get<_Np>(std::forward<_Variant>(__lhs)) \ + __op __get<_Np>(std::forward<_Variant>(__rhs)); \ } - template<typename _Variant, size_t _Np> - 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(<, __erased_less_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE template<typename _Tp> constexpr size_t @@ -800,63 +802,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>(__ptr); } - template<typename... _Types> - constexpr bool operator==(const variant<_Types...>& __lhs, - const variant<_Types...>& __rhs) - { - return __lhs._M_equal_to(__rhs, std::index_sequence_for<_Types...>{}); - } - - template<typename... _Types> - constexpr inline bool - operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs == __rhs); } - - template<typename... _Types> - constexpr inline bool - operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { - return __lhs._M_less_than(__rhs, std::index_sequence_for<_Types...>{}); - } - - template<typename... _Types> - constexpr inline bool - operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return __rhs < __lhs; } - - template<typename... _Types> - constexpr inline bool - operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs > __rhs); } + struct monostate { }; - template<typename... _Types> - constexpr inline bool - operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) - { return !(__lhs < __rhs); } +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op, __name) \ + template<typename... _Types> \ + 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(<, __erased_less_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE template<typename _Visitor, typename... _Variants> 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<typename... _Types> inline enable_if_t<(is_move_constructible_v<_Types> && ...) && (is_swappable_v<_Types> && ...)> @@ -1122,51 +1092,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: - template<size_t... __indices> - static constexpr bool - (*_S_equal_to_vtable[])(const variant&, const variant&) = - { &__detail::__variant::__erased_equal_to< - const variant&, __indices>... }; - - template<size_t... __indices> - static constexpr bool - (*_S_less_than_vtable[])(const variant&, const variant&) = - { &__detail::__variant::__erased_less_than< - const variant&, __indices>... }; - - template<size_t... __indices> - 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<size_t... __indices> \ + static constexpr bool \ + (*_S##__name##_vtable[])(const variant&, const variant&) = \ + { &__detail::__variant::__name<const variant&, __indices>... }; \ + template<size_t... __indices> \ + 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()) \ + /* Intentinoal modulo addition. */ \ + return __lhs_index + 1 __op __rhs_index + 1; \ + return _S##__name##_vtable<__indices...>[__lhs_index](*this, __rhs); \ } - template<size_t... __indices> - 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(<, __erased_less_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, __erased_less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, __erased_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, __erased_not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, __erased_greater_than) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, __erased_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<size_t _Np, typename _Vp> friend constexpr decltype(auto) __detail::__variant:: @@ -1182,15 +1133,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif __get_storage(_Vp&& __v); - template<typename... _Tp> - friend constexpr bool - operator==(const variant<_Tp...>& __lhs, - const variant<_Tp...>& __rhs); +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__op) \ + template<typename... _Tp> \ + 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<typename... _Tp> - friend constexpr bool - operator<(const variant<_Tp...>& __lhs, - const variant<_Tp...>& __rhs); +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE }; template<size_t _Np, typename... _Types> diff --git a/libstdc++-v3/testsuite/20_util/variant/compile.cc b/libstdc++-v3/testsuite/20_util/variant/compile.cc index 65f4326..8320013 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 121fd22..db4529e 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<int, string>(2) < variant<int, string>("a"))); VERIFY((variant<string, int>(2) > variant<string, int>("a"))); + + { + variant<int, AlwaysThrow> 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()