1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);
19 #include <iterator> // std::size
21 #include <type_traits>
24 #include "test_macros.h"
26 template<class T
, class U
>
27 constexpr auto has_partial_order(T
&& t
, U
&& u
)
28 -> decltype(std::partial_order(static_cast<T
&&>(t
), static_cast<U
&&>(u
)), true)
33 constexpr bool has_partial_order(...) {
40 std::strong_ordering
partial_order(const A
&, const A
&) { return std::strong_ordering::less
; }
41 std::strong_ordering
partial_order(const A
&, const B
&);
46 // If the decayed types of E and F differ, partial_order(E, F) is ill-formed.
48 static_assert( has_partial_order(1, 2));
49 static_assert(!has_partial_order(1, (short)2));
50 static_assert(!has_partial_order(1, 2.0));
51 static_assert(!has_partial_order(1.0f
, 2.0));
53 static_assert( has_partial_order((int*)nullptr, (int*)nullptr));
54 static_assert(!has_partial_order((int*)nullptr, (const int*)nullptr));
55 static_assert(!has_partial_order((const int*)nullptr, (int*)nullptr));
56 static_assert( has_partial_order((const int*)nullptr, (const int*)nullptr));
60 static_assert( has_partial_order(a
, a
));
61 static_assert(!has_partial_order(a
, b
));
66 std::strong_ordering
partial_order(A
&, A
&&) { return std::strong_ordering::less
; }
67 std::weak_ordering
partial_order(A
&&, A
&&) { return std::weak_ordering::equivalent
; }
68 std::strong_ordering
partial_order(const A
&, const A
&);
71 friend int partial_order(B
, B
);
75 explicit operator std::partial_ordering() const { return std::partial_ordering::less
; }
79 friend PartialOrder
partial_order(C
& lhs
, C
&) { lhs
.touched
= true; return PartialOrder(); }
85 // Otherwise, partial_ordering(partial_order(E, F))
86 // if it is a well-formed expression with overload resolution performed
87 // in a context that does not include a declaration of std::partial_order.
89 // Test that partial_order does not const-qualify the forwarded arguments.
91 assert(std::partial_order(a
, std::move(a
)) == std::partial_ordering::less
);
92 assert(std::partial_order(std::move(a
), std::move(a
)) == std::partial_ordering::equivalent
);
94 // The type of partial_order(e,f) must be explicitly convertible to partial_ordering.
96 static_assert(!has_partial_order(b
, b
));
99 ASSERT_SAME_TYPE(decltype(std::partial_order(c1
, c2
)), std::partial_ordering
);
100 assert(std::partial_order(c1
, c2
) == std::partial_ordering::less
);
106 // Compare to N12::A.
108 bool operator==(const A
&, const A
&);
109 constexpr std::partial_ordering
operator<=>(A
&, A
&&) { return std::partial_ordering::less
; }
110 constexpr std::partial_ordering
operator<=>(A
&&, A
&&) { return std::partial_ordering::equivalent
; }
111 std::partial_ordering
operator<=>(const A
&, const A
&);
112 static_assert(std::three_way_comparable
<A
>);
115 std::partial_ordering
operator<=>(const B
&) const; // lacks operator==
117 static_assert(!std::three_way_comparable
<B
>);
121 bool operator==(const C
&) const;
122 constexpr std::partial_ordering
operator<=>(const C
& rhs
) const {
124 return std::partial_ordering::equivalent
;
127 static_assert(std::three_way_comparable
<C
>);
130 constexpr bool test_1_3()
132 // Otherwise, partial_ordering(compare_three_way()(E, F)) if it is a well-formed expression.
134 // Test neither partial_order nor compare_three_way const-qualify the forwarded arguments.
136 assert(std::partial_order(a
, std::move(a
)) == std::partial_ordering::less
);
137 assert(std::partial_order(std::move(a
), std::move(a
)) == std::partial_ordering::equivalent
);
140 static_assert(!has_partial_order(b
, b
));
142 // Test that the arguments are passed to <=> in the correct order.
143 bool c1_touched
= false;
144 bool c2_touched
= false;
145 N13::C c1
= {&c1_touched
};
146 N13::C c2
= {&c2_touched
};
147 assert(std::partial_order(c1
, c2
) == std::partial_ordering::equivalent
);
151 // For partial_order, this bullet point takes care of floating-point types;
152 // they receive their natural partial order.
155 F nan
= std::numeric_limits
<F
>::quiet_NaN();
156 assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less
);
157 assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent
);
158 #ifndef TEST_COMPILER_GCC // GCC can't compare NaN to non-NaN in a constant-expression
159 assert(std::partial_order(nan
, F(1)) == std::partial_ordering::unordered
);
161 assert(std::partial_order(nan
, nan
) == std::partial_ordering::unordered
);
165 F nan
= std::numeric_limits
<F
>::quiet_NaN();
166 assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less
);
167 assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent
);
168 #ifndef TEST_COMPILER_GCC
169 assert(std::partial_order(nan
, F(1)) == std::partial_ordering::unordered
);
171 assert(std::partial_order(nan
, nan
) == std::partial_ordering::unordered
);
174 using F
= long double;
175 F nan
= std::numeric_limits
<F
>::quiet_NaN();
176 assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less
);
177 assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent
);
178 #ifndef TEST_COMPILER_GCC
179 assert(std::partial_order(nan
, F(1)) == std::partial_ordering::unordered
);
181 assert(std::partial_order(nan
, nan
) == std::partial_ordering::unordered
);
189 constexpr std::strong_ordering
weak_order(A
&, A
&&) { return std::strong_ordering::less
; }
190 constexpr std::strong_ordering
weak_order(A
&&, A
&&) { return std::strong_ordering::equal
; }
191 std::strong_ordering
weak_order(const A
&, const A
&);
194 friend std::partial_ordering
weak_order(B
, B
);
198 operator std::strong_ordering() const { return std::strong_ordering::less
; }
201 friend StrongOrder
weak_order(C
& lhs
, C
&);
205 constexpr explicit operator std::weak_ordering() const { return std::weak_ordering::less
; }
206 operator std::partial_ordering() const = delete;
209 bool touched
= false;
210 friend constexpr WeakOrder
weak_order(D
& lhs
, D
&) { lhs
.touched
= true; return WeakOrder(); }
214 constexpr bool test_1_4()
216 // Otherwise, partial_ordering(weak_order(E, F)) [that is, std::weak_order]
217 // if it is a well-formed expression.
219 // Test that partial_order and weak_order do not const-qualify the forwarded arguments.
221 assert(std::partial_order(a
, std::move(a
)) == std::partial_ordering::less
);
222 assert(std::partial_order(std::move(a
), std::move(a
)) == std::partial_ordering::equivalent
);
224 // The type of ADL weak_order(e,f) must be explicitly convertible to weak_ordering
225 // (not just to partial_ordering), or else std::weak_order(e,f) won't exist.
227 static_assert(!has_partial_order(b
, b
));
229 // The type of ADL weak_order(e,f) must be explicitly convertible to weak_ordering
230 // (not just to strong_ordering), or else std::weak_order(e,f) won't exist.
232 static_assert(!has_partial_order(c
, c
));
235 ASSERT_SAME_TYPE(decltype(std::partial_order(d1
, d2
)), std::partial_ordering
);
236 assert(std::partial_order(d1
, d2
) == std::partial_ordering::less
);
243 int main(int, char**)
250 static_assert(test_1_3());
251 static_assert(test_1_4());