diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-02-21 12:02:15 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-02-21 17:12:39 +0000 |
commit | 9e58988061f4175896de11af0caf9bdd48c9b046 (patch) | |
tree | 324fbbc0975fb49b2901280792048f5d95aa90b7 /libstdc++-v3/include | |
parent | 131fbdd7b750faecd7c874dc97adb01b53d073ea (diff) | |
download | gcc-9e58988061f4175896de11af0caf9bdd48c9b046.zip gcc-9e58988061f4175896de11af0caf9bdd48c9b046.tar.gz gcc-9e58988061f4175896de11af0caf9bdd48c9b046.tar.bz2 |
libstdc++: Define <=> for tuple, optional and variant
Another piece of P1614R2.
* include/std/optional (operator<=>(optional<T>, optional<U>))
(operator<=>(optional<T>, nullopt), operator<=>(optional<T>, U)):
Define for C++20.
* include/std/tuple (__tuple_cmp): New helper function for <=>.
(operator<=>(tuple<T...>, tuple<U>...)): Define for C++20.
* include/std/variant (operator<=>(variant<T...>, variant<T...>))
(operator<=>(monostate, monostate)): Define for C++20.
* testsuite/20_util/optional/relops/three_way.cc: New test.
* testsuite/20_util/tuple/comparison_operators/three_way.cc: New test.
* testsuite/20_util/variant/89851.cc: Move to ...
* testsuite/20_util/variant/relops/89851.cc: ... here.
* testsuite/20_util/variant/90008.cc: Move to ...
* testsuite/20_util/variant/relops/90008.cc: ... here.
* testsuite/20_util/variant/relops/three_way.cc: New test.
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/std/optional | 26 | ||||
-rw-r--r-- | libstdc++-v3/include/std/tuple | 33 | ||||
-rw-r--r-- | libstdc++-v3/include/std/variant | 47 |
3 files changed, 102 insertions, 4 deletions
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index b920a14..37c2ba7 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -41,6 +41,9 @@ #include <bits/exception_defines.h> #include <bits/functional_hash.h> #include <bits/enable_special_members.h> +#if __cplusplus > 201703L +# include <compare> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -1027,12 +1030,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); } +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp, three_way_comparable_with<_Tp> _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) + { + return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); + } +#endif + // Comparisons with nullopt. template<typename _Tp> constexpr bool operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept { return !__lhs; } +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp> + constexpr strong_ordering + operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept + { return bool(__x) <=> false; } +#else template<typename _Tp> constexpr bool operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept @@ -1087,6 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr bool operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept { return !__rhs; } +#endif // three-way-comparison // Comparisons with value type. template<typename _Tp, typename _Up> @@ -1161,6 +1180,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())> { return !__rhs || __lhs >= *__rhs; } +#ifdef __cpp_lib_three_way_comparison + template<typename _Tp, typename _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const _Up& __v) + { return bool(__x) ? *__x <=> __v : strong_ordering::less; } +#endif + // Swap and creation functions. // _GLIBCXX_RESOLVE_LIB_DEFECTS diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 3829d84..8089477 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -39,6 +39,9 @@ #include <array> #include <bits/uses_allocator.h> #include <bits/invoke.h> +#if __cplusplus > 201703L +# include <compare> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -1397,6 +1400,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __compare::__eq(__t, __u); } +#if __cpp_lib_three_way_comparison + template<typename _Cat, typename _Tp, typename _Up> + constexpr _Cat + __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) + { return _Cat::equivalent; } + + template<typename _Cat, typename _Tp, typename _Up, + size_t _Idx0, size_t... _Idxs> + constexpr _Cat + __tuple_cmp(const _Tp& __t, const _Up& __u, + index_sequence<_Idx0, _Idxs...>) + { + auto __c + = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); + if (__c != 0) + return __c; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); + } + + template<typename... _Tps, typename... _Ups> + constexpr + common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> + operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) + { + using _Cat + = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); + } +#else template<typename... _TElements, typename... _UElements> constexpr bool operator<(const tuple<_TElements...>& __t, @@ -1433,6 +1465,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>=(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u) { return !(__t < __u); } +#endif // three_way_comparison // NB: DR 705. template<typename... _Elements> diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 9568b71..258a5fb 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -45,6 +45,9 @@ #include <bits/stl_iterator_base_types.h> #include <bits/stl_iterator_base_funcs.h> #include <bits/stl_construct.h> +#if __cplusplus > 201703L +# include <compare> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -1181,10 +1184,7 @@ namespace __variant __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ }, __rhs); \ return __ret; \ - } \ -\ - constexpr bool operator __OP(monostate, monostate) noexcept \ - { return 0 __OP 0; } + } _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) @@ -1195,6 +1195,45 @@ namespace __variant #undef _VARIANT_RELATION_FUNCTION_TEMPLATE + constexpr bool operator==(monostate, monostate) noexcept { return true; } + +#ifdef __cpp_lib_three_way_comparison + template<typename... _Types> + requires (three_way_comparable<_Types> && ...) + constexpr + common_comparison_category_t<compare_three_way_result_t<_Types>...> + operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w) + { + common_comparison_category_t<compare_three_way_result_t<_Types>...> __ret + = strong_ordering::equal; + + __detail::__variant::__raw_idx_visit( + [&__ret, &__v] (auto&& __w_mem, auto __w_index) mutable + { + if constexpr (__w_index != variant_npos) + { + if (__v.index() == __w_index) + { + auto& __this_mem = std::get<__w_index>(__v); + __ret = __this_mem <=> __w_mem; + return; + } + } + __ret = (__v.index() + 1) <=> (__w_index + 1); + }, __w); + return __ret; + } + + constexpr strong_ordering + operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } +#else + constexpr bool operator!=(monostate, monostate) noexcept { return false; } + 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; } +#endif + template<typename _Visitor, typename... _Variants> constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); |