1 | //===----------------------------------------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | |
11 | // <compare> |
12 | |
13 | // template<class T> constexpr strong_ordering compare_strong_order_fallback(const T& a, const T& b); |
14 | |
15 | #include <compare> |
16 | |
17 | #include <cassert> |
18 | #include <cmath> |
19 | #include <iterator> // std::size |
20 | #include <limits> |
21 | #include <type_traits> |
22 | #include <utility> |
23 | |
24 | #include "test_macros.h" |
25 | |
26 | #if defined(__i386__) |
27 | #define TEST_BUGGY_SIGNALING_NAN |
28 | #endif |
29 | |
30 | template<class T, class U> |
31 | constexpr auto has_strong_order(T&& t, U&& u) |
32 | -> decltype(std::compare_strong_order_fallback(static_cast<T&&>(t), static_cast<U&&>(u)), true) |
33 | { |
34 | return true; |
35 | } |
36 | |
37 | constexpr bool has_strong_order(...) { |
38 | return false; |
39 | } |
40 | |
41 | namespace N11 { |
42 | struct A {}; |
43 | struct B {}; |
44 | std::strong_ordering strong_order(const A&, const A&) { return std::strong_ordering::less; } |
45 | std::strong_ordering strong_order(const A&, const B&); |
46 | } |
47 | |
48 | void test_1_1() |
49 | { |
50 | // If the decayed types of E and F differ, strong_order(E, F) is ill-formed. |
51 | |
52 | static_assert( has_strong_order(1, 2)); |
53 | static_assert(!has_strong_order(1, (short)2)); |
54 | static_assert(!has_strong_order(1, 2.0)); |
55 | static_assert(!has_strong_order(1.0f, 2.0)); |
56 | |
57 | static_assert( has_strong_order((int*)nullptr, (int*)nullptr)); |
58 | static_assert(!has_strong_order((int*)nullptr, (const int*)nullptr)); |
59 | static_assert(!has_strong_order((const int*)nullptr, (int*)nullptr)); |
60 | static_assert( has_strong_order((const int*)nullptr, (const int*)nullptr)); |
61 | |
62 | N11::A a; |
63 | N11::B b; |
64 | static_assert( has_strong_order(a, a)); |
65 | static_assert(!has_strong_order(a, b)); |
66 | } |
67 | |
68 | namespace N12 { |
69 | struct A {}; |
70 | std::strong_ordering strong_order(A&, A&&) { return std::strong_ordering::less; } |
71 | std::strong_ordering strong_order(A&&, A&&) { return std::strong_ordering::equal; } |
72 | std::strong_ordering strong_order(const A&, const A&); |
73 | |
74 | struct B { |
75 | friend std::weak_ordering strong_order(B&, B&); |
76 | }; |
77 | |
78 | struct StrongOrder { |
79 | explicit operator std::strong_ordering() const { return std::strong_ordering::less; } |
80 | }; |
81 | struct C { |
82 | bool touched = false; |
83 | friend StrongOrder strong_order(C& lhs, C&) { lhs.touched = true; return StrongOrder(); } |
84 | }; |
85 | } |
86 | |
87 | void test_1_2() |
88 | { |
89 | // Otherwise, strong_ordering(strong_order(E, F)) |
90 | // if it is a well-formed expression with overload resolution performed |
91 | // in a context that does not include a declaration of std::strong_order. |
92 | |
93 | // Test that strong_order does not const-qualify the forwarded arguments. |
94 | N12::A a; |
95 | assert(std::compare_strong_order_fallback(a, std::move(a)) == std::strong_ordering::less); |
96 | assert(std::compare_strong_order_fallback(std::move(a), std::move(a)) == std::strong_ordering::equal); |
97 | |
98 | // The type of strong_order(e,f) must be explicitly convertible to strong_ordering. |
99 | N12::B b; |
100 | static_assert(!has_strong_order(b, b)); |
101 | |
102 | N12::C c1, c2; |
103 | ASSERT_SAME_TYPE(decltype(std::compare_strong_order_fallback(c1, c2)), std::strong_ordering); |
104 | assert(std::compare_strong_order_fallback(c1, c2) == std::strong_ordering::less); |
105 | assert(c1.touched); |
106 | assert(!c2.touched); |
107 | } |
108 | |
109 | template<class F> |
110 | constexpr bool test_1_3() |
111 | { |
112 | // Otherwise, if the decayed type T of E is a floating-point type, |
113 | // yields a value of type strong_ordering that is consistent with |
114 | // the ordering observed by T's comparison operators, |
115 | // and if numeric_limits<T>::is_iec559 is true, is additionally consistent with |
116 | // the totalOrder operation as specified in ISO/IEC/IEEE 60559. |
117 | |
118 | static_assert(std::numeric_limits<F>::is_iec559); |
119 | |
120 | ASSERT_SAME_TYPE(decltype(std::compare_strong_order_fallback(F(0), F(0))), std::strong_ordering); |
121 | |
122 | F v[] = { |
123 | -std::numeric_limits<F>::infinity(), |
124 | std::numeric_limits<F>::lowest(), // largest (finite) negative number |
125 | F(-1.0), F(-0.1), |
126 | -std::numeric_limits<F>::min(), // smallest (normal) negative number |
127 | F(-0.0), // negative zero |
128 | F(0.0), |
129 | std::numeric_limits<F>::min(), // smallest (normal) positive number |
130 | F(0.1), F(1.0), F(2.0), F(3.14), |
131 | std::numeric_limits<F>::max(), // largest (finite) positive number |
132 | std::numeric_limits<F>::infinity(), |
133 | }; |
134 | |
135 | static_assert(std::size(v) == 14); |
136 | |
137 | // Sanity-check that array 'v' is indeed in the right order. |
138 | for (int i=0; i < 14; ++i) { |
139 | for (int j=0; j < 14; ++j) { |
140 | auto naturalOrder = (v[i] <=> v[j]); |
141 | if (v[i] == 0 && v[j] == 0) { |
142 | assert(naturalOrder == std::partial_ordering::equivalent); |
143 | } else { |
144 | assert(naturalOrder == std::partial_ordering::unordered || naturalOrder == (i <=> j)); |
145 | } |
146 | } |
147 | } |
148 | |
149 | assert(std::compare_strong_order_fallback(v[0], v[0]) == std::strong_ordering::equal); |
150 | assert(std::compare_strong_order_fallback(v[0], v[1]) == std::strong_ordering::less); |
151 | assert(std::compare_strong_order_fallback(v[0], v[2]) == std::strong_ordering::less); |
152 | assert(std::compare_strong_order_fallback(v[0], v[3]) == std::strong_ordering::less); |
153 | assert(std::compare_strong_order_fallback(v[0], v[4]) == std::strong_ordering::less); |
154 | assert(std::compare_strong_order_fallback(v[0], v[5]) == std::strong_ordering::less); |
155 | assert(std::compare_strong_order_fallback(v[0], v[6]) == std::strong_ordering::less); |
156 | assert(std::compare_strong_order_fallback(v[0], v[7]) == std::strong_ordering::less); |
157 | assert(std::compare_strong_order_fallback(v[0], v[8]) == std::strong_ordering::less); |
158 | assert(std::compare_strong_order_fallback(v[0], v[9]) == std::strong_ordering::less); |
159 | assert(std::compare_strong_order_fallback(v[0], v[10]) == std::strong_ordering::less); |
160 | assert(std::compare_strong_order_fallback(v[0], v[11]) == std::strong_ordering::less); |
161 | assert(std::compare_strong_order_fallback(v[0], v[12]) == std::strong_ordering::less); |
162 | assert(std::compare_strong_order_fallback(v[0], v[13]) == std::strong_ordering::less); |
163 | assert(std::compare_strong_order_fallback(v[1], v[0]) == std::strong_ordering::greater); |
164 | assert(std::compare_strong_order_fallback(v[1], v[1]) == std::strong_ordering::equal); |
165 | assert(std::compare_strong_order_fallback(v[1], v[2]) == std::strong_ordering::less); |
166 | assert(std::compare_strong_order_fallback(v[1], v[3]) == std::strong_ordering::less); |
167 | assert(std::compare_strong_order_fallback(v[1], v[4]) == std::strong_ordering::less); |
168 | assert(std::compare_strong_order_fallback(v[1], v[5]) == std::strong_ordering::less); |
169 | assert(std::compare_strong_order_fallback(v[1], v[6]) == std::strong_ordering::less); |
170 | assert(std::compare_strong_order_fallback(v[1], v[7]) == std::strong_ordering::less); |
171 | assert(std::compare_strong_order_fallback(v[1], v[8]) == std::strong_ordering::less); |
172 | assert(std::compare_strong_order_fallback(v[1], v[9]) == std::strong_ordering::less); |
173 | assert(std::compare_strong_order_fallback(v[1], v[10]) == std::strong_ordering::less); |
174 | assert(std::compare_strong_order_fallback(v[1], v[11]) == std::strong_ordering::less); |
175 | assert(std::compare_strong_order_fallback(v[1], v[12]) == std::strong_ordering::less); |
176 | assert(std::compare_strong_order_fallback(v[1], v[13]) == std::strong_ordering::less); |
177 | assert(std::compare_strong_order_fallback(v[2], v[0]) == std::strong_ordering::greater); |
178 | assert(std::compare_strong_order_fallback(v[2], v[1]) == std::strong_ordering::greater); |
179 | assert(std::compare_strong_order_fallback(v[2], v[2]) == std::strong_ordering::equal); |
180 | assert(std::compare_strong_order_fallback(v[2], v[3]) == std::strong_ordering::less); |
181 | assert(std::compare_strong_order_fallback(v[2], v[4]) == std::strong_ordering::less); |
182 | assert(std::compare_strong_order_fallback(v[2], v[5]) == std::strong_ordering::less); |
183 | assert(std::compare_strong_order_fallback(v[2], v[6]) == std::strong_ordering::less); |
184 | assert(std::compare_strong_order_fallback(v[2], v[7]) == std::strong_ordering::less); |
185 | assert(std::compare_strong_order_fallback(v[2], v[8]) == std::strong_ordering::less); |
186 | assert(std::compare_strong_order_fallback(v[2], v[9]) == std::strong_ordering::less); |
187 | assert(std::compare_strong_order_fallback(v[2], v[10]) == std::strong_ordering::less); |
188 | assert(std::compare_strong_order_fallback(v[2], v[11]) == std::strong_ordering::less); |
189 | assert(std::compare_strong_order_fallback(v[2], v[12]) == std::strong_ordering::less); |
190 | assert(std::compare_strong_order_fallback(v[2], v[13]) == std::strong_ordering::less); |
191 | assert(std::compare_strong_order_fallback(v[3], v[0]) == std::strong_ordering::greater); |
192 | assert(std::compare_strong_order_fallback(v[3], v[1]) == std::strong_ordering::greater); |
193 | assert(std::compare_strong_order_fallback(v[3], v[2]) == std::strong_ordering::greater); |
194 | assert(std::compare_strong_order_fallback(v[3], v[3]) == std::strong_ordering::equal); |
195 | assert(std::compare_strong_order_fallback(v[3], v[4]) == std::strong_ordering::less); |
196 | assert(std::compare_strong_order_fallback(v[3], v[5]) == std::strong_ordering::less); |
197 | assert(std::compare_strong_order_fallback(v[3], v[6]) == std::strong_ordering::less); |
198 | assert(std::compare_strong_order_fallback(v[3], v[7]) == std::strong_ordering::less); |
199 | assert(std::compare_strong_order_fallback(v[3], v[8]) == std::strong_ordering::less); |
200 | assert(std::compare_strong_order_fallback(v[3], v[9]) == std::strong_ordering::less); |
201 | assert(std::compare_strong_order_fallback(v[3], v[10]) == std::strong_ordering::less); |
202 | assert(std::compare_strong_order_fallback(v[3], v[11]) == std::strong_ordering::less); |
203 | assert(std::compare_strong_order_fallback(v[3], v[12]) == std::strong_ordering::less); |
204 | assert(std::compare_strong_order_fallback(v[3], v[13]) == std::strong_ordering::less); |
205 | assert(std::compare_strong_order_fallback(v[4], v[0]) == std::strong_ordering::greater); |
206 | assert(std::compare_strong_order_fallback(v[4], v[1]) == std::strong_ordering::greater); |
207 | assert(std::compare_strong_order_fallback(v[4], v[2]) == std::strong_ordering::greater); |
208 | assert(std::compare_strong_order_fallback(v[4], v[3]) == std::strong_ordering::greater); |
209 | assert(std::compare_strong_order_fallback(v[4], v[4]) == std::strong_ordering::equal); |
210 | assert(std::compare_strong_order_fallback(v[4], v[5]) == std::strong_ordering::less); |
211 | assert(std::compare_strong_order_fallback(v[4], v[6]) == std::strong_ordering::less); |
212 | assert(std::compare_strong_order_fallback(v[4], v[7]) == std::strong_ordering::less); |
213 | assert(std::compare_strong_order_fallback(v[4], v[8]) == std::strong_ordering::less); |
214 | assert(std::compare_strong_order_fallback(v[4], v[9]) == std::strong_ordering::less); |
215 | assert(std::compare_strong_order_fallback(v[4], v[10]) == std::strong_ordering::less); |
216 | assert(std::compare_strong_order_fallback(v[4], v[11]) == std::strong_ordering::less); |
217 | assert(std::compare_strong_order_fallback(v[4], v[12]) == std::strong_ordering::less); |
218 | assert(std::compare_strong_order_fallback(v[4], v[13]) == std::strong_ordering::less); |
219 | assert(std::compare_strong_order_fallback(v[5], v[0]) == std::strong_ordering::greater); |
220 | assert(std::compare_strong_order_fallback(v[5], v[1]) == std::strong_ordering::greater); |
221 | assert(std::compare_strong_order_fallback(v[5], v[2]) == std::strong_ordering::greater); |
222 | assert(std::compare_strong_order_fallback(v[5], v[3]) == std::strong_ordering::greater); |
223 | assert(std::compare_strong_order_fallback(v[5], v[4]) == std::strong_ordering::greater); |
224 | assert(std::compare_strong_order_fallback(v[5], v[5]) == std::strong_ordering::equal); |
225 | assert(std::compare_strong_order_fallback(v[5], v[6]) == std::strong_ordering::less); |
226 | assert(std::compare_strong_order_fallback(v[5], v[7]) == std::strong_ordering::less); |
227 | assert(std::compare_strong_order_fallback(v[5], v[8]) == std::strong_ordering::less); |
228 | assert(std::compare_strong_order_fallback(v[5], v[9]) == std::strong_ordering::less); |
229 | assert(std::compare_strong_order_fallback(v[5], v[10]) == std::strong_ordering::less); |
230 | assert(std::compare_strong_order_fallback(v[5], v[11]) == std::strong_ordering::less); |
231 | assert(std::compare_strong_order_fallback(v[5], v[12]) == std::strong_ordering::less); |
232 | assert(std::compare_strong_order_fallback(v[5], v[13]) == std::strong_ordering::less); |
233 | assert(std::compare_strong_order_fallback(v[6], v[0]) == std::strong_ordering::greater); |
234 | assert(std::compare_strong_order_fallback(v[6], v[1]) == std::strong_ordering::greater); |
235 | assert(std::compare_strong_order_fallback(v[6], v[2]) == std::strong_ordering::greater); |
236 | assert(std::compare_strong_order_fallback(v[6], v[3]) == std::strong_ordering::greater); |
237 | assert(std::compare_strong_order_fallback(v[6], v[4]) == std::strong_ordering::greater); |
238 | assert(std::compare_strong_order_fallback(v[6], v[5]) == std::strong_ordering::greater); |
239 | assert(std::compare_strong_order_fallback(v[6], v[6]) == std::strong_ordering::equal); |
240 | assert(std::compare_strong_order_fallback(v[6], v[7]) == std::strong_ordering::less); |
241 | assert(std::compare_strong_order_fallback(v[6], v[8]) == std::strong_ordering::less); |
242 | assert(std::compare_strong_order_fallback(v[6], v[9]) == std::strong_ordering::less); |
243 | assert(std::compare_strong_order_fallback(v[6], v[10]) == std::strong_ordering::less); |
244 | assert(std::compare_strong_order_fallback(v[6], v[11]) == std::strong_ordering::less); |
245 | assert(std::compare_strong_order_fallback(v[6], v[12]) == std::strong_ordering::less); |
246 | assert(std::compare_strong_order_fallback(v[6], v[13]) == std::strong_ordering::less); |
247 | assert(std::compare_strong_order_fallback(v[7], v[0]) == std::strong_ordering::greater); |
248 | assert(std::compare_strong_order_fallback(v[7], v[1]) == std::strong_ordering::greater); |
249 | assert(std::compare_strong_order_fallback(v[7], v[2]) == std::strong_ordering::greater); |
250 | assert(std::compare_strong_order_fallback(v[7], v[3]) == std::strong_ordering::greater); |
251 | assert(std::compare_strong_order_fallback(v[7], v[4]) == std::strong_ordering::greater); |
252 | assert(std::compare_strong_order_fallback(v[7], v[5]) == std::strong_ordering::greater); |
253 | assert(std::compare_strong_order_fallback(v[7], v[6]) == std::strong_ordering::greater); |
254 | assert(std::compare_strong_order_fallback(v[7], v[7]) == std::strong_ordering::equal); |
255 | assert(std::compare_strong_order_fallback(v[7], v[8]) == std::strong_ordering::less); |
256 | assert(std::compare_strong_order_fallback(v[7], v[9]) == std::strong_ordering::less); |
257 | assert(std::compare_strong_order_fallback(v[7], v[10]) == std::strong_ordering::less); |
258 | assert(std::compare_strong_order_fallback(v[7], v[11]) == std::strong_ordering::less); |
259 | assert(std::compare_strong_order_fallback(v[7], v[12]) == std::strong_ordering::less); |
260 | assert(std::compare_strong_order_fallback(v[7], v[13]) == std::strong_ordering::less); |
261 | assert(std::compare_strong_order_fallback(v[8], v[0]) == std::strong_ordering::greater); |
262 | assert(std::compare_strong_order_fallback(v[8], v[1]) == std::strong_ordering::greater); |
263 | assert(std::compare_strong_order_fallback(v[8], v[2]) == std::strong_ordering::greater); |
264 | assert(std::compare_strong_order_fallback(v[8], v[3]) == std::strong_ordering::greater); |
265 | assert(std::compare_strong_order_fallback(v[8], v[4]) == std::strong_ordering::greater); |
266 | assert(std::compare_strong_order_fallback(v[8], v[5]) == std::strong_ordering::greater); |
267 | assert(std::compare_strong_order_fallback(v[8], v[6]) == std::strong_ordering::greater); |
268 | assert(std::compare_strong_order_fallback(v[8], v[7]) == std::strong_ordering::greater); |
269 | assert(std::compare_strong_order_fallback(v[8], v[8]) == std::strong_ordering::equal); |
270 | assert(std::compare_strong_order_fallback(v[8], v[9]) == std::strong_ordering::less); |
271 | assert(std::compare_strong_order_fallback(v[8], v[10]) == std::strong_ordering::less); |
272 | assert(std::compare_strong_order_fallback(v[8], v[11]) == std::strong_ordering::less); |
273 | assert(std::compare_strong_order_fallback(v[8], v[12]) == std::strong_ordering::less); |
274 | assert(std::compare_strong_order_fallback(v[8], v[13]) == std::strong_ordering::less); |
275 | assert(std::compare_strong_order_fallback(v[9], v[0]) == std::strong_ordering::greater); |
276 | assert(std::compare_strong_order_fallback(v[9], v[1]) == std::strong_ordering::greater); |
277 | assert(std::compare_strong_order_fallback(v[9], v[2]) == std::strong_ordering::greater); |
278 | assert(std::compare_strong_order_fallback(v[9], v[3]) == std::strong_ordering::greater); |
279 | assert(std::compare_strong_order_fallback(v[9], v[4]) == std::strong_ordering::greater); |
280 | assert(std::compare_strong_order_fallback(v[9], v[5]) == std::strong_ordering::greater); |
281 | assert(std::compare_strong_order_fallback(v[9], v[6]) == std::strong_ordering::greater); |
282 | assert(std::compare_strong_order_fallback(v[9], v[7]) == std::strong_ordering::greater); |
283 | assert(std::compare_strong_order_fallback(v[9], v[8]) == std::strong_ordering::greater); |
284 | assert(std::compare_strong_order_fallback(v[9], v[9]) == std::strong_ordering::equal); |
285 | assert(std::compare_strong_order_fallback(v[9], v[10]) == std::strong_ordering::less); |
286 | assert(std::compare_strong_order_fallback(v[9], v[11]) == std::strong_ordering::less); |
287 | assert(std::compare_strong_order_fallback(v[9], v[12]) == std::strong_ordering::less); |
288 | assert(std::compare_strong_order_fallback(v[9], v[13]) == std::strong_ordering::less); |
289 | assert(std::compare_strong_order_fallback(v[10], v[0]) == std::strong_ordering::greater); |
290 | assert(std::compare_strong_order_fallback(v[10], v[1]) == std::strong_ordering::greater); |
291 | assert(std::compare_strong_order_fallback(v[10], v[2]) == std::strong_ordering::greater); |
292 | assert(std::compare_strong_order_fallback(v[10], v[3]) == std::strong_ordering::greater); |
293 | assert(std::compare_strong_order_fallback(v[10], v[4]) == std::strong_ordering::greater); |
294 | assert(std::compare_strong_order_fallback(v[10], v[5]) == std::strong_ordering::greater); |
295 | assert(std::compare_strong_order_fallback(v[10], v[6]) == std::strong_ordering::greater); |
296 | assert(std::compare_strong_order_fallback(v[10], v[7]) == std::strong_ordering::greater); |
297 | assert(std::compare_strong_order_fallback(v[10], v[8]) == std::strong_ordering::greater); |
298 | assert(std::compare_strong_order_fallback(v[10], v[9]) == std::strong_ordering::greater); |
299 | assert(std::compare_strong_order_fallback(v[10], v[10]) == std::strong_ordering::equal); |
300 | assert(std::compare_strong_order_fallback(v[10], v[11]) == std::strong_ordering::less); |
301 | assert(std::compare_strong_order_fallback(v[10], v[12]) == std::strong_ordering::less); |
302 | assert(std::compare_strong_order_fallback(v[10], v[13]) == std::strong_ordering::less); |
303 | assert(std::compare_strong_order_fallback(v[11], v[0]) == std::strong_ordering::greater); |
304 | assert(std::compare_strong_order_fallback(v[11], v[1]) == std::strong_ordering::greater); |
305 | assert(std::compare_strong_order_fallback(v[11], v[2]) == std::strong_ordering::greater); |
306 | assert(std::compare_strong_order_fallback(v[11], v[3]) == std::strong_ordering::greater); |
307 | assert(std::compare_strong_order_fallback(v[11], v[4]) == std::strong_ordering::greater); |
308 | assert(std::compare_strong_order_fallback(v[11], v[5]) == std::strong_ordering::greater); |
309 | assert(std::compare_strong_order_fallback(v[11], v[6]) == std::strong_ordering::greater); |
310 | assert(std::compare_strong_order_fallback(v[11], v[7]) == std::strong_ordering::greater); |
311 | assert(std::compare_strong_order_fallback(v[11], v[8]) == std::strong_ordering::greater); |
312 | assert(std::compare_strong_order_fallback(v[11], v[9]) == std::strong_ordering::greater); |
313 | assert(std::compare_strong_order_fallback(v[11], v[10]) == std::strong_ordering::greater); |
314 | assert(std::compare_strong_order_fallback(v[11], v[11]) == std::strong_ordering::equal); |
315 | assert(std::compare_strong_order_fallback(v[11], v[12]) == std::strong_ordering::less); |
316 | assert(std::compare_strong_order_fallback(v[11], v[13]) == std::strong_ordering::less); |
317 | assert(std::compare_strong_order_fallback(v[12], v[0]) == std::strong_ordering::greater); |
318 | assert(std::compare_strong_order_fallback(v[12], v[1]) == std::strong_ordering::greater); |
319 | assert(std::compare_strong_order_fallback(v[12], v[2]) == std::strong_ordering::greater); |
320 | assert(std::compare_strong_order_fallback(v[12], v[3]) == std::strong_ordering::greater); |
321 | assert(std::compare_strong_order_fallback(v[12], v[4]) == std::strong_ordering::greater); |
322 | assert(std::compare_strong_order_fallback(v[12], v[5]) == std::strong_ordering::greater); |
323 | assert(std::compare_strong_order_fallback(v[12], v[6]) == std::strong_ordering::greater); |
324 | assert(std::compare_strong_order_fallback(v[12], v[7]) == std::strong_ordering::greater); |
325 | assert(std::compare_strong_order_fallback(v[12], v[8]) == std::strong_ordering::greater); |
326 | assert(std::compare_strong_order_fallback(v[12], v[9]) == std::strong_ordering::greater); |
327 | assert(std::compare_strong_order_fallback(v[12], v[10]) == std::strong_ordering::greater); |
328 | assert(std::compare_strong_order_fallback(v[12], v[11]) == std::strong_ordering::greater); |
329 | assert(std::compare_strong_order_fallback(v[12], v[12]) == std::strong_ordering::equal); |
330 | assert(std::compare_strong_order_fallback(v[12], v[13]) == std::strong_ordering::less); |
331 | assert(std::compare_strong_order_fallback(v[13], v[0]) == std::strong_ordering::greater); |
332 | assert(std::compare_strong_order_fallback(v[13], v[1]) == std::strong_ordering::greater); |
333 | assert(std::compare_strong_order_fallback(v[13], v[2]) == std::strong_ordering::greater); |
334 | assert(std::compare_strong_order_fallback(v[13], v[3]) == std::strong_ordering::greater); |
335 | assert(std::compare_strong_order_fallback(v[13], v[4]) == std::strong_ordering::greater); |
336 | assert(std::compare_strong_order_fallback(v[13], v[5]) == std::strong_ordering::greater); |
337 | assert(std::compare_strong_order_fallback(v[13], v[6]) == std::strong_ordering::greater); |
338 | assert(std::compare_strong_order_fallback(v[13], v[7]) == std::strong_ordering::greater); |
339 | assert(std::compare_strong_order_fallback(v[13], v[8]) == std::strong_ordering::greater); |
340 | assert(std::compare_strong_order_fallback(v[13], v[9]) == std::strong_ordering::greater); |
341 | assert(std::compare_strong_order_fallback(v[13], v[10]) == std::strong_ordering::greater); |
342 | assert(std::compare_strong_order_fallback(v[13], v[11]) == std::strong_ordering::greater); |
343 | assert(std::compare_strong_order_fallback(v[13], v[12]) == std::strong_ordering::greater); |
344 | assert(std::compare_strong_order_fallback(v[13], v[13]) == std::strong_ordering::equal); |
345 | |
346 | |
347 | // There's no way to produce a specifically positive or negative NAN |
348 | // at compile-time, so the NAN-related tests must be runtime-only. |
349 | |
350 | if (!std::is_constant_evaluated()) { |
351 | F nq = std::copysign(std::numeric_limits<F>::quiet_NaN(), F(-1)); |
352 | F ns = std::copysign(std::numeric_limits<F>::signaling_NaN(), F(-1)); |
353 | F ps = std::copysign(std::numeric_limits<F>::signaling_NaN(), F(+1)); |
354 | F pq = std::copysign(std::numeric_limits<F>::quiet_NaN(), F(+1)); |
355 | |
356 | assert(std::compare_strong_order_fallback(nq, nq) == std::strong_ordering::equal); |
357 | #ifndef TEST_BUGGY_SIGNALING_NAN |
358 | assert(std::compare_strong_order_fallback(nq, ns) == std::strong_ordering::less); |
359 | #endif |
360 | for (int i=0; i < 14; ++i) { |
361 | assert(std::compare_strong_order_fallback(nq, v[i]) == std::strong_ordering::less); |
362 | } |
363 | assert(std::compare_strong_order_fallback(nq, ps) == std::strong_ordering::less); |
364 | assert(std::compare_strong_order_fallback(nq, pq) == std::strong_ordering::less); |
365 | |
366 | #ifndef TEST_BUGGY_SIGNALING_NAN |
367 | assert(std::compare_strong_order_fallback(ns, nq) == std::strong_ordering::greater); |
368 | #endif |
369 | assert(std::compare_strong_order_fallback(ns, ns) == std::strong_ordering::equal); |
370 | for (int i=0; i < 14; ++i) { |
371 | assert(std::compare_strong_order_fallback(ns, v[i]) == std::strong_ordering::less); |
372 | } |
373 | assert(std::compare_strong_order_fallback(ns, ps) == std::strong_ordering::less); |
374 | assert(std::compare_strong_order_fallback(ns, pq) == std::strong_ordering::less); |
375 | |
376 | assert(std::compare_strong_order_fallback(ps, nq) == std::strong_ordering::greater); |
377 | assert(std::compare_strong_order_fallback(ps, ns) == std::strong_ordering::greater); |
378 | for (int i=0; i < 14; ++i) { |
379 | assert(std::compare_strong_order_fallback(ps, v[i]) == std::strong_ordering::greater); |
380 | } |
381 | assert(std::compare_strong_order_fallback(ps, ps) == std::strong_ordering::equal); |
382 | #ifndef TEST_BUGGY_SIGNALING_NAN |
383 | assert(std::compare_strong_order_fallback(ps, pq) == std::strong_ordering::less); |
384 | #endif |
385 | |
386 | assert(std::compare_strong_order_fallback(pq, nq) == std::strong_ordering::greater); |
387 | assert(std::compare_strong_order_fallback(pq, ns) == std::strong_ordering::greater); |
388 | for (int i=0; i < 14; ++i) { |
389 | assert(std::compare_strong_order_fallback(pq, v[i]) == std::strong_ordering::greater); |
390 | } |
391 | #ifndef TEST_BUGGY_SIGNALING_NAN |
392 | assert(std::compare_strong_order_fallback(pq, ps) == std::strong_ordering::greater); |
393 | #endif |
394 | assert(std::compare_strong_order_fallback(pq, pq) == std::strong_ordering::equal); |
395 | } |
396 | |
397 | return true; |
398 | } |
399 | |
400 | namespace N14 { |
401 | // Compare to N12::A. |
402 | struct A {}; |
403 | bool operator==(const A&, const A&); |
404 | constexpr std::strong_ordering operator<=>(A&, A&&) { return std::strong_ordering::less; } |
405 | constexpr std::strong_ordering operator<=>(A&&, A&&) { return std::strong_ordering::equal; } |
406 | std::strong_ordering operator<=>(const A&, const A&); |
407 | static_assert(std::three_way_comparable<A>); |
408 | |
409 | struct B { |
410 | std::strong_ordering operator<=>(const B&) const; // lacks operator== |
411 | }; |
412 | static_assert(!std::three_way_comparable<B>); |
413 | |
414 | struct C { |
415 | bool *touched; |
416 | bool operator==(const C&) const; |
417 | constexpr std::strong_ordering operator<=>(const C& rhs) const { |
418 | *rhs.touched = true; |
419 | return std::strong_ordering::equal; |
420 | } |
421 | }; |
422 | static_assert(std::three_way_comparable<C>); |
423 | } |
424 | |
425 | constexpr bool test_1_4() |
426 | { |
427 | // Otherwise, strong_ordering(compare_three_way()(E, F)) if it is a well-formed expression. |
428 | |
429 | // Test neither strong_order nor compare_three_way const-qualify the forwarded arguments. |
430 | N14::A a; |
431 | assert(std::compare_strong_order_fallback(a, std::move(a)) == std::strong_ordering::less); |
432 | assert(std::compare_strong_order_fallback(std::move(a), std::move(a)) == std::strong_ordering::equal); |
433 | |
434 | N14::B b; |
435 | static_assert(!has_strong_order(b, b)); |
436 | |
437 | // Test that the arguments are passed to <=> in the correct order. |
438 | bool c1_touched = false; |
439 | bool c2_touched = false; |
440 | N14::C c1 = {.touched: &c1_touched}; |
441 | N14::C c2 = {.touched: &c2_touched}; |
442 | assert(std::compare_strong_order_fallback(c1, c2) == std::strong_ordering::equal); |
443 | assert(!c1_touched); |
444 | assert(c2_touched); |
445 | |
446 | return true; |
447 | } |
448 | |
449 | namespace N2 { |
450 | struct Stats { |
451 | int eq = 0; |
452 | int lt = 0; |
453 | }; |
454 | struct A { |
455 | Stats *stats_; |
456 | double value_; |
457 | constexpr explicit A(Stats *stats, double value) : stats_(stats), value_(value) {} |
458 | friend constexpr bool operator==(A a, A b) { a.stats_->eq += 1; return a.value_ == b.value_; } |
459 | friend constexpr bool operator<(A a, A b) { a.stats_->lt += 1; return a.value_ < b.value_; } |
460 | }; |
461 | struct NoEquality { |
462 | friend bool operator<(NoEquality, NoEquality); |
463 | }; |
464 | struct VC1 { |
465 | // Deliberately asymmetric `const` qualifiers here. |
466 | friend bool operator==(const VC1&, VC1&); |
467 | friend bool operator<(const VC1&, VC1&); |
468 | }; |
469 | struct VC2 { |
470 | // Deliberately asymmetric `const` qualifiers here. |
471 | friend bool operator==(const VC2&, VC2&); |
472 | friend bool operator==(VC2&, const VC2&) = delete; |
473 | friend bool operator<(const VC2&, VC2&); |
474 | friend bool operator<(VC2&, const VC2&); |
475 | }; |
476 | } |
477 | |
478 | constexpr bool test_2() |
479 | { |
480 | { |
481 | N2::Stats stats; |
482 | assert(std::compare_strong_order_fallback(N2::A(&stats, 1), N2::A(nullptr, 1)) == std::strong_ordering::equal); |
483 | assert(stats.eq == 1 && stats.lt == 0); |
484 | stats = {}; |
485 | assert(std::compare_strong_order_fallback(N2::A(&stats, 1), N2::A(nullptr, 2)) == std::strong_ordering::less); |
486 | assert(stats.eq == 1 && stats.lt == 1); |
487 | stats = {}; |
488 | assert(std::compare_strong_order_fallback(N2::A(&stats, 2), N2::A(nullptr, 1)) == std::strong_ordering::greater); |
489 | assert(stats.eq == 1 && stats.lt == 1); |
490 | } |
491 | { |
492 | N2::NoEquality ne; |
493 | assert(!has_strong_order(ne, ne)); |
494 | } |
495 | { |
496 | // LWG3465: (cvc < vc) is well-formed, (vc < cvc) is not. That's fine, for strong ordering. |
497 | N2::VC1 vc; |
498 | const N2::VC1 cvc; |
499 | assert( has_strong_order(cvc, vc)); |
500 | assert(!has_strong_order(vc, cvc)); |
501 | } |
502 | { |
503 | // LWG3465: (cvc == vc) is well-formed, (vc == cvc) is not. That's fine. |
504 | N2::VC2 vc; |
505 | const N2::VC2 cvc; |
506 | assert( has_strong_order(cvc, vc)); |
507 | assert(!has_strong_order(vc, cvc)); |
508 | } |
509 | return true; |
510 | } |
511 | |
512 | int main(int, char**) |
513 | { |
514 | test_1_1(); |
515 | test_1_2(); |
516 | test_1_3<float>(); |
517 | test_1_3<double>(); |
518 | // test_1_3<long double>(); // UNIMPLEMENTED |
519 | test_1_4(); |
520 | test_2(); |
521 | |
522 | static_assert(test_1_3<float>()); |
523 | static_assert(test_1_3<double>()); |
524 | // static_assert(test_1_3<long double>()); // UNIMPLEMENTED |
525 | static_assert(test_1_4()); |
526 | static_assert(test_2()); |
527 | |
528 | return 0; |
529 | } |
530 | |