aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2020-02-21 12:02:15 +0000
committerJonathan Wakely <jwakely@redhat.com>2020-02-21 17:12:39 +0000
commit9e58988061f4175896de11af0caf9bdd48c9b046 (patch)
tree324fbbc0975fb49b2901280792048f5d95aa90b7 /libstdc++-v3/include
parent131fbdd7b750faecd7c874dc97adb01b53d073ea (diff)
downloadgcc-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/optional26
-rw-r--r--libstdc++-v3/include/std/tuple33
-rw-r--r--libstdc++-v3/include/std/variant47
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&&...);