This is incomplete because std::strong_order doesn't support
floating-point types.
The partial_order and weak_order tests use VERIFY instead of
static_assert because of PR 92431.
* libsupc++/compare (strong_order, weak_order, partial_order)
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback): Define customization point objects
for C++20.
* testsuite/18_support/comparisons/algorithms/partial_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/strong_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: New test.
Tested powerpc64le-linux, committed to trunk.
commit e4dc0c07ed229d6efca300b42753fcd365db0085
Author: Jonathan Wakely
Date: Thu Nov 7 21:58:46 2019 +
libsupc++: Implement comparison algorithms for C++20
This is incomplete because std::strong_order doesn't support
floating-point types.
The partial_order and weak_order tests use VERIFY instead of
static_assert because of PR 92431.
* libsupc++/compare (strong_order, weak_order, partial_order)
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback): Define customization point objects
for C++20.
* testsuite/18_support/comparisons/algorithms/partial_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/strong_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: New
test.
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 94728e29de8..289145dea56 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -576,20 +576,346 @@ namespace std
using is_transparent = void;
};
+ namespace __cmp_cust
+ {
+template
+ constexpr weak_ordering
+ __fp_weak_ordering(_Tp __e, _Tp __f)
+ {
+ // Returns an integer with the same sign as the argument, and magnitude
+ // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5
+ auto __cat = [](_Tp __fp) -> int {
+ const int __sign = __builtin_signbit(__fp) ? -1 : 1;
+ if (__builtin_isnormal(__fp))
+ return (__fp == 0 ? 1 : 3) * __sign;
+ if (__builtin_isnan(__fp))
+ return 5 * __sign;
+ if (int __inf = __builtin_isinf_sign(__fp))
+ return 4 * __inf;
+ return 2 * __sign;
+ };
+
+ auto __po = __e <=> __f;
+ if (is_lt(__po))
+ return weak_ordering::less;
+ else if (is_gt(__po))
+ return weak_ordering::greater;
+ else if (__po == partial_ordering::equivalent)
+ return weak_ordering::equivalent;
+ else // unordered, at least one argument is NaN
+ {
+ // return -1 for negative nan, +1 for positive nan, 0 otherwise.
+ auto __isnan_sign = [](_Tp __fp) -> int {
+ return __builtin_isnan(__fp)
+ ? __builtin_signbit(__fp) ? -1 : 1
+ : 0;
+ };
+ auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f);
+ if (is_eq(__ord))
+ return weak_ordering::equivalent;
+ else if (is_lt(__ord))
+ return weak_ordering::less;
+ else
+ return weak_ordering::greater;
+ }
+ }
+
+template
+ concept __adl_strong = requires(_Tp&& __t, _Up&& __u)
+ {
+ strong_ordering(strong_order(static_cast<_Tp&&>(__t),
+ static_cast<_Up&&>(__u)));
+ };
+
+template
+ concept __adl_weak = requires(_Tp&& __t, _Up&& __u)
+ {
+ weak_ordering(weak_order(static_cast<_Tp&&>(__t),
+ static_cast<_Up&&>(__u)));
+ };
+
+template
+ concept __adl_partial = requires(_Tp&& __t, _Up&& __u)
+ {
+ partial_ordering(partial_order(static_cast<_Tp&&>(__t),
+static_cast<_Up&&>(__u)));
+ };
+
+template
+ concept __op_cmp = requires(_Tp&& __t, _Up&& __u)
+ {
+ _Ord(static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u));
+ };
+
+template
+ concept __strongly_ordered
+ = __adl_strong<_Tp, _Up>
+ // FIXME: || floating_point>
+ || __op_cmp;
+
+class _Strong_order
+{
+ template
+ static constexpr bool
+ _S_noexcept()
+ {
+ if constexpr (floating_point>)
+ return true;
+ else if constexpr (__adl_strong<_Tp, _Up>)
+ return noexcept(strong_ordering(strong_order(std::declval<_Tp>(),
+std::declval<_Up>(;
+ else if constexpr (__op_cmp)
+ return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
+ }
+
+ friend class _W