1 | // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> |
2 | // Copyright (C) 2023 The Qt Company Ltd. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QCOMPARE_H |
6 | #define QCOMPARE_H |
7 | |
8 | #if 0 |
9 | #pragma qt_class(QtCompare) |
10 | #endif |
11 | |
12 | #include <QtCore/qglobal.h> |
13 | #include <QtCore/qcompare_impl.h> |
14 | |
15 | #ifdef __cpp_lib_bit_cast |
16 | #include <bit> |
17 | #endif |
18 | #ifdef __cpp_lib_three_way_comparison |
19 | #include <compare> |
20 | #endif |
21 | |
22 | QT_BEGIN_NAMESPACE |
23 | |
24 | namespace QtPrivate { |
25 | using CompareUnderlyingType = qint8; |
26 | constexpr CompareUnderlyingType LegacyUncomparableValue = -127; // historic Qt value |
27 | |
28 | // [cmp.categories.pre] / 1 |
29 | enum class Ordering : CompareUnderlyingType |
30 | { |
31 | Equal = 0, |
32 | Equivalent = Equal, |
33 | Less = -1, |
34 | Greater = 1 |
35 | }; |
36 | |
37 | enum class Uncomparable : CompareUnderlyingType |
38 | { |
39 | Unordered = |
40 | #if defined(_LIBCPP_VERSION) // libc++ |
41 | -127 |
42 | #elif defined(__GLIBCXX__) // libstdc++ |
43 | 2 |
44 | #else // assume MSSTL |
45 | -128 |
46 | #endif |
47 | }; |
48 | |
49 | } // namespace QtPrivate |
50 | |
51 | namespace QtOrderingPrivate { |
52 | |
53 | template <typename O> |
54 | constexpr O reversed(O o) noexcept |
55 | { |
56 | // https://eel.is/c++draft/cmp.partialord#5 |
57 | return is_lt(o) ? O::greater : |
58 | is_gt(o) ? O::less : |
59 | /*else*/ o ; |
60 | } |
61 | |
62 | } // namespace QtOrderingPrivate |
63 | |
64 | namespace Qt { |
65 | |
66 | class weak_ordering; |
67 | class strong_ordering; |
68 | |
69 | class partial_ordering |
70 | { |
71 | public: |
72 | static const partial_ordering less; |
73 | static const partial_ordering equivalent; |
74 | static const partial_ordering greater; |
75 | static const partial_ordering unordered; |
76 | |
77 | friend constexpr bool operator==(partial_ordering lhs, |
78 | QtPrivate::CompareAgainstLiteralZero) noexcept |
79 | { return lhs.isOrdered() && lhs.m_order == 0; } |
80 | |
81 | friend constexpr bool operator!=(partial_ordering lhs, |
82 | QtPrivate::CompareAgainstLiteralZero) noexcept |
83 | { return !lhs.isOrdered() || lhs.m_order != 0; } |
84 | |
85 | friend constexpr bool operator< (partial_ordering lhs, |
86 | QtPrivate::CompareAgainstLiteralZero) noexcept |
87 | { return lhs.isOrdered() && lhs.m_order < 0; } |
88 | |
89 | friend constexpr bool operator<=(partial_ordering lhs, |
90 | QtPrivate::CompareAgainstLiteralZero) noexcept |
91 | { return lhs.isOrdered() && lhs.m_order <= 0; } |
92 | |
93 | friend constexpr bool operator> (partial_ordering lhs, |
94 | QtPrivate::CompareAgainstLiteralZero) noexcept |
95 | { return lhs.isOrdered() && lhs.m_order > 0; } |
96 | |
97 | friend constexpr bool operator>=(partial_ordering lhs, |
98 | QtPrivate::CompareAgainstLiteralZero) noexcept |
99 | { return lhs.isOrdered() && lhs.m_order >= 0; } |
100 | |
101 | |
102 | friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, |
103 | partial_ordering rhs) noexcept |
104 | { return rhs.isOrdered() && 0 == rhs.m_order; } |
105 | |
106 | friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, |
107 | partial_ordering rhs) noexcept |
108 | { return !rhs.isOrdered() || 0 != rhs.m_order; } |
109 | |
110 | friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, |
111 | partial_ordering rhs) noexcept |
112 | { return rhs.isOrdered() && 0 < rhs.m_order; } |
113 | |
114 | friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, |
115 | partial_ordering rhs) noexcept |
116 | { return rhs.isOrdered() && 0 <= rhs.m_order; } |
117 | |
118 | friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, |
119 | partial_ordering rhs) noexcept |
120 | { return rhs.isOrdered() && 0 > rhs.m_order; } |
121 | |
122 | friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, |
123 | partial_ordering rhs) noexcept |
124 | { return rhs.isOrdered() && 0 >= rhs.m_order; } |
125 | |
126 | |
127 | #ifdef __cpp_lib_three_way_comparison |
128 | friend constexpr std::partial_ordering |
129 | operator<=>(partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept |
130 | { return lhs; } // https://eel.is/c++draft/cmp.partialord#4 |
131 | |
132 | friend constexpr std::partial_ordering |
133 | operator<=>(QtPrivate::CompareAgainstLiteralZero, partial_ordering rhs) noexcept |
134 | { return QtOrderingPrivate::reversed(rhs); } |
135 | #endif // __cpp_lib_three_way_comparison |
136 | |
137 | |
138 | friend constexpr bool operator==(partial_ordering lhs, partial_ordering rhs) noexcept |
139 | { return lhs.m_order == rhs.m_order; } |
140 | |
141 | friend constexpr bool operator!=(partial_ordering lhs, partial_ordering rhs) noexcept |
142 | { return lhs.m_order != rhs.m_order; } |
143 | |
144 | #ifdef __cpp_lib_three_way_comparison |
145 | constexpr Q_IMPLICIT partial_ordering(std::partial_ordering stdorder) noexcept |
146 | { |
147 | if (stdorder == std::partial_ordering::less) |
148 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less); |
149 | else if (stdorder == std::partial_ordering::equivalent) |
150 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent); |
151 | else if (stdorder == std::partial_ordering::greater) |
152 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater); |
153 | else if (stdorder == std::partial_ordering::unordered) |
154 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); |
155 | } |
156 | |
157 | constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept |
158 | { |
159 | static_assert(sizeof(*this) == sizeof(std::partial_ordering)); |
160 | #ifdef __cpp_lib_bit_cast |
161 | return std::bit_cast<std::partial_ordering>(*this); |
162 | #else |
163 | using O = QtPrivate::Ordering; |
164 | using U = QtPrivate::Uncomparable; |
165 | using R = std::partial_ordering; |
166 | switch (m_order) { |
167 | case qToUnderlying(O::Less): return R::less; |
168 | case qToUnderlying(O::Greater): return R::greater; |
169 | case qToUnderlying(O::Equivalent): return R::equivalent; |
170 | case qToUnderlying(U::Unordered): return R::unordered; |
171 | } |
172 | Q_UNREACHABLE_RETURN(R::unordered); |
173 | #endif // __cpp_lib_bit_cast |
174 | } |
175 | |
176 | friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept |
177 | { return static_cast<std::partial_ordering>(lhs) == rhs; } |
178 | |
179 | friend constexpr bool operator!=(partial_ordering lhs, std::partial_ordering rhs) noexcept |
180 | { return static_cast<std::partial_ordering>(lhs) != rhs; } |
181 | |
182 | friend constexpr bool operator==(std::partial_ordering lhs, partial_ordering rhs) noexcept |
183 | { return lhs == static_cast<std::partial_ordering>(rhs); } |
184 | |
185 | friend constexpr bool operator!=(std::partial_ordering lhs, partial_ordering rhs) noexcept |
186 | { return lhs != static_cast<std::partial_ordering>(rhs); } |
187 | |
188 | friend constexpr bool operator==(partial_ordering lhs, std::strong_ordering rhs) noexcept |
189 | { return static_cast<std::partial_ordering>(lhs) == rhs; } |
190 | |
191 | friend constexpr bool operator!=(partial_ordering lhs, std::strong_ordering rhs) noexcept |
192 | { return static_cast<std::partial_ordering>(lhs) != rhs; } |
193 | |
194 | friend constexpr bool operator==(std::strong_ordering lhs, partial_ordering rhs) noexcept |
195 | { return lhs == static_cast<std::partial_ordering>(rhs); } |
196 | |
197 | friend constexpr bool operator!=(std::strong_ordering lhs, partial_ordering rhs) noexcept |
198 | { return lhs != static_cast<std::partial_ordering>(rhs); } |
199 | |
200 | friend constexpr bool operator==(partial_ordering lhs, std::weak_ordering rhs) noexcept |
201 | { return static_cast<std::partial_ordering>(lhs) == rhs; } |
202 | |
203 | friend constexpr bool operator!=(partial_ordering lhs, std::weak_ordering rhs) noexcept |
204 | { return static_cast<std::partial_ordering>(lhs) != rhs; } |
205 | |
206 | friend constexpr bool operator==(std::weak_ordering lhs, partial_ordering rhs) noexcept |
207 | { return lhs == static_cast<std::partial_ordering>(rhs); } |
208 | |
209 | friend constexpr bool operator!=(std::weak_ordering lhs, partial_ordering rhs) noexcept |
210 | { return lhs != static_cast<std::partial_ordering>(rhs); } |
211 | #endif // __cpp_lib_three_way_comparison |
212 | |
213 | private: |
214 | friend class weak_ordering; |
215 | friend class strong_ordering; |
216 | |
217 | constexpr explicit partial_ordering(QtPrivate::Ordering order) noexcept |
218 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
219 | {} |
220 | constexpr explicit partial_ordering(QtPrivate::Uncomparable order) noexcept |
221 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
222 | {} |
223 | |
224 | QT_WARNING_PUSH |
225 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903 |
226 | QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant" ) |
227 | QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant" ) |
228 | friend constexpr bool is_eq (partial_ordering o) noexcept { return o == 0; } |
229 | friend constexpr bool is_neq (partial_ordering o) noexcept { return o != 0; } |
230 | friend constexpr bool is_lt (partial_ordering o) noexcept { return o < 0; } |
231 | friend constexpr bool is_lteq(partial_ordering o) noexcept { return o <= 0; } |
232 | friend constexpr bool is_gt (partial_ordering o) noexcept { return o > 0; } |
233 | friend constexpr bool is_gteq(partial_ordering o) noexcept { return o >= 0; } |
234 | QT_WARNING_POP |
235 | |
236 | // instead of the exposition only is_ordered member in [cmp.partialord], |
237 | // use a private function |
238 | constexpr bool isOrdered() const noexcept |
239 | { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); } |
240 | |
241 | QtPrivate::CompareUnderlyingType m_order; |
242 | }; |
243 | |
244 | inline constexpr partial_ordering partial_ordering::less(QtPrivate::Ordering::Less); |
245 | inline constexpr partial_ordering partial_ordering::equivalent(QtPrivate::Ordering::Equivalent); |
246 | inline constexpr partial_ordering partial_ordering::greater(QtPrivate::Ordering::Greater); |
247 | inline constexpr partial_ordering partial_ordering::unordered(QtPrivate::Uncomparable::Unordered); |
248 | |
249 | class weak_ordering |
250 | { |
251 | public: |
252 | static const weak_ordering less; |
253 | static const weak_ordering equivalent; |
254 | static const weak_ordering greater; |
255 | |
256 | constexpr Q_IMPLICIT operator partial_ordering() const noexcept |
257 | { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); } |
258 | |
259 | friend constexpr bool operator==(weak_ordering lhs, |
260 | QtPrivate::CompareAgainstLiteralZero) noexcept |
261 | { return lhs.m_order == 0; } |
262 | |
263 | friend constexpr bool operator!=(weak_ordering lhs, |
264 | QtPrivate::CompareAgainstLiteralZero) noexcept |
265 | { return lhs.m_order != 0; } |
266 | |
267 | friend constexpr bool operator< (weak_ordering lhs, |
268 | QtPrivate::CompareAgainstLiteralZero) noexcept |
269 | { return lhs.m_order < 0; } |
270 | |
271 | friend constexpr bool operator<=(weak_ordering lhs, |
272 | QtPrivate::CompareAgainstLiteralZero) noexcept |
273 | { return lhs.m_order <= 0; } |
274 | |
275 | friend constexpr bool operator> (weak_ordering lhs, |
276 | QtPrivate::CompareAgainstLiteralZero) noexcept |
277 | { return lhs.m_order > 0; } |
278 | |
279 | friend constexpr bool operator>=(weak_ordering lhs, |
280 | QtPrivate::CompareAgainstLiteralZero) noexcept |
281 | { return lhs.m_order >= 0; } |
282 | |
283 | |
284 | friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, |
285 | weak_ordering rhs) noexcept |
286 | { return 0 == rhs.m_order; } |
287 | |
288 | friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, |
289 | weak_ordering rhs) noexcept |
290 | { return 0 != rhs.m_order; } |
291 | |
292 | friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, |
293 | weak_ordering rhs) noexcept |
294 | { return 0 < rhs.m_order; } |
295 | |
296 | friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, |
297 | weak_ordering rhs) noexcept |
298 | { return 0 <= rhs.m_order; } |
299 | |
300 | friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, |
301 | weak_ordering rhs) noexcept |
302 | { return 0 > rhs.m_order; } |
303 | |
304 | friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, |
305 | weak_ordering rhs) noexcept |
306 | { return 0 >= rhs.m_order; } |
307 | |
308 | |
309 | #ifdef __cpp_lib_three_way_comparison |
310 | friend constexpr std::weak_ordering |
311 | operator<=>(weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept |
312 | { return lhs; } // https://eel.is/c++draft/cmp.weakord#5 |
313 | |
314 | friend constexpr std::weak_ordering |
315 | operator<=>(QtPrivate::CompareAgainstLiteralZero, weak_ordering rhs) noexcept |
316 | { return QtOrderingPrivate::reversed(rhs); } |
317 | #endif // __cpp_lib_three_way_comparison |
318 | |
319 | |
320 | friend constexpr bool operator==(weak_ordering lhs, weak_ordering rhs) noexcept |
321 | { return lhs.m_order == rhs.m_order; } |
322 | |
323 | friend constexpr bool operator!=(weak_ordering lhs, weak_ordering rhs) noexcept |
324 | { return lhs.m_order != rhs.m_order; } |
325 | |
326 | friend constexpr bool operator==(weak_ordering lhs, partial_ordering rhs) noexcept |
327 | { return static_cast<partial_ordering>(lhs) == rhs; } |
328 | |
329 | friend constexpr bool operator!=(weak_ordering lhs, partial_ordering rhs) noexcept |
330 | { return static_cast<partial_ordering>(lhs) != rhs; } |
331 | |
332 | friend constexpr bool operator==(partial_ordering lhs, weak_ordering rhs) noexcept |
333 | { return lhs == static_cast<partial_ordering>(rhs); } |
334 | |
335 | friend constexpr bool operator!=(partial_ordering lhs, weak_ordering rhs) noexcept |
336 | { return lhs != static_cast<partial_ordering>(rhs); } |
337 | |
338 | #ifdef __cpp_lib_three_way_comparison |
339 | constexpr Q_IMPLICIT weak_ordering(std::weak_ordering stdorder) noexcept |
340 | { |
341 | if (stdorder == std::weak_ordering::less) |
342 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less); |
343 | else if (stdorder == std::weak_ordering::equivalent) |
344 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent); |
345 | else if (stdorder == std::weak_ordering::greater) |
346 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater); |
347 | } |
348 | |
349 | constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept |
350 | { |
351 | static_assert(sizeof(*this) == sizeof(std::weak_ordering)); |
352 | #ifdef __cpp_lib_bit_cast |
353 | return std::bit_cast<std::weak_ordering>(*this); |
354 | #else |
355 | using O = QtPrivate::Ordering; |
356 | using R = std::weak_ordering; |
357 | switch (m_order) { |
358 | case qToUnderlying(O::Less): return R::less; |
359 | case qToUnderlying(O::Greater): return R::greater; |
360 | case qToUnderlying(O::Equivalent): return R::equivalent; |
361 | } |
362 | Q_UNREACHABLE_RETURN(R::equivalent); |
363 | #endif // __cpp_lib_bit_cast |
364 | } |
365 | |
366 | friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept |
367 | { return static_cast<std::weak_ordering>(lhs) == rhs; } |
368 | |
369 | friend constexpr bool operator!=(weak_ordering lhs, std::weak_ordering rhs) noexcept |
370 | { return static_cast<std::weak_ordering>(lhs) != rhs; } |
371 | |
372 | friend constexpr bool operator==(weak_ordering lhs, std::partial_ordering rhs) noexcept |
373 | { return static_cast<std::weak_ordering>(lhs) == rhs; } |
374 | |
375 | friend constexpr bool operator!=(weak_ordering lhs, std::partial_ordering rhs) noexcept |
376 | { return static_cast<std::weak_ordering>(lhs) != rhs; } |
377 | |
378 | friend constexpr bool operator==(weak_ordering lhs, std::strong_ordering rhs) noexcept |
379 | { return static_cast<std::weak_ordering>(lhs) == rhs; } |
380 | |
381 | friend constexpr bool operator!=(weak_ordering lhs, std::strong_ordering rhs) noexcept |
382 | { return static_cast<std::weak_ordering>(lhs) != rhs; } |
383 | |
384 | friend constexpr bool operator==(std::weak_ordering lhs, weak_ordering rhs) noexcept |
385 | { return lhs == static_cast<std::weak_ordering>(rhs); } |
386 | |
387 | friend constexpr bool operator!=(std::weak_ordering lhs, weak_ordering rhs) noexcept |
388 | { return lhs != static_cast<std::weak_ordering>(rhs); } |
389 | |
390 | friend constexpr bool operator==(std::partial_ordering lhs, weak_ordering rhs) noexcept |
391 | { return lhs == static_cast<std::weak_ordering>(rhs); } |
392 | |
393 | friend constexpr bool operator!=(std::partial_ordering lhs, weak_ordering rhs) noexcept |
394 | { return lhs != static_cast<std::weak_ordering>(rhs); } |
395 | |
396 | friend constexpr bool operator==(std::strong_ordering lhs, weak_ordering rhs) noexcept |
397 | { return lhs == static_cast<std::weak_ordering>(rhs); } |
398 | |
399 | friend constexpr bool operator!=(std::strong_ordering lhs, weak_ordering rhs) noexcept |
400 | { return lhs != static_cast<std::weak_ordering>(rhs); } |
401 | #endif // __cpp_lib_three_way_comparison |
402 | |
403 | private: |
404 | friend class strong_ordering; |
405 | |
406 | constexpr explicit weak_ordering(QtPrivate::Ordering order) noexcept |
407 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
408 | {} |
409 | |
410 | QT_WARNING_PUSH |
411 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903 |
412 | QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant" ) |
413 | QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant" ) |
414 | friend constexpr bool is_eq (weak_ordering o) noexcept { return o == 0; } |
415 | friend constexpr bool is_neq (weak_ordering o) noexcept { return o != 0; } |
416 | friend constexpr bool is_lt (weak_ordering o) noexcept { return o < 0; } |
417 | friend constexpr bool is_lteq(weak_ordering o) noexcept { return o <= 0; } |
418 | friend constexpr bool is_gt (weak_ordering o) noexcept { return o > 0; } |
419 | friend constexpr bool is_gteq(weak_ordering o) noexcept { return o >= 0; } |
420 | QT_WARNING_POP |
421 | |
422 | QtPrivate::CompareUnderlyingType m_order; |
423 | }; |
424 | |
425 | inline constexpr weak_ordering weak_ordering::less(QtPrivate::Ordering::Less); |
426 | inline constexpr weak_ordering weak_ordering::equivalent(QtPrivate::Ordering::Equivalent); |
427 | inline constexpr weak_ordering weak_ordering::greater(QtPrivate::Ordering::Greater); |
428 | |
429 | class strong_ordering |
430 | { |
431 | public: |
432 | static const strong_ordering less; |
433 | static const strong_ordering equivalent; |
434 | static const strong_ordering equal; |
435 | static const strong_ordering greater; |
436 | |
437 | constexpr Q_IMPLICIT operator partial_ordering() const noexcept |
438 | { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); } |
439 | |
440 | constexpr Q_IMPLICIT operator weak_ordering() const noexcept |
441 | { return weak_ordering(static_cast<QtPrivate::Ordering>(m_order)); } |
442 | |
443 | friend constexpr bool operator==(strong_ordering lhs, |
444 | QtPrivate::CompareAgainstLiteralZero) noexcept |
445 | { return lhs.m_order == 0; } |
446 | |
447 | friend constexpr bool operator!=(strong_ordering lhs, |
448 | QtPrivate::CompareAgainstLiteralZero) noexcept |
449 | { return lhs.m_order != 0; } |
450 | |
451 | friend constexpr bool operator< (strong_ordering lhs, |
452 | QtPrivate::CompareAgainstLiteralZero) noexcept |
453 | { return lhs.m_order < 0; } |
454 | |
455 | friend constexpr bool operator<=(strong_ordering lhs, |
456 | QtPrivate::CompareAgainstLiteralZero) noexcept |
457 | { return lhs.m_order <= 0; } |
458 | |
459 | friend constexpr bool operator> (strong_ordering lhs, |
460 | QtPrivate::CompareAgainstLiteralZero) noexcept |
461 | { return lhs.m_order > 0; } |
462 | |
463 | friend constexpr bool operator>=(strong_ordering lhs, |
464 | QtPrivate::CompareAgainstLiteralZero) noexcept |
465 | { return lhs.m_order >= 0; } |
466 | |
467 | |
468 | friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, |
469 | strong_ordering rhs) noexcept |
470 | { return 0 == rhs.m_order; } |
471 | |
472 | friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, |
473 | strong_ordering rhs) noexcept |
474 | { return 0 != rhs.m_order; } |
475 | |
476 | friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, |
477 | strong_ordering rhs) noexcept |
478 | { return 0 < rhs.m_order; } |
479 | |
480 | friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, |
481 | strong_ordering rhs) noexcept |
482 | { return 0 <= rhs.m_order; } |
483 | |
484 | friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, |
485 | strong_ordering rhs) noexcept |
486 | { return 0 > rhs.m_order; } |
487 | |
488 | friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, |
489 | strong_ordering rhs) noexcept |
490 | { return 0 >= rhs.m_order; } |
491 | |
492 | |
493 | #ifdef __cpp_lib_three_way_comparison |
494 | friend constexpr std::strong_ordering |
495 | operator<=>(strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept |
496 | { return lhs; } // https://eel.is/c++draft/cmp.strongord#6 |
497 | |
498 | friend constexpr std::strong_ordering |
499 | operator<=>(QtPrivate::CompareAgainstLiteralZero, strong_ordering rhs) noexcept |
500 | { return QtOrderingPrivate::reversed(rhs); } |
501 | #endif // __cpp_lib_three_way_comparison |
502 | |
503 | |
504 | friend constexpr bool operator==(strong_ordering lhs, strong_ordering rhs) noexcept |
505 | { return lhs.m_order == rhs.m_order; } |
506 | |
507 | friend constexpr bool operator!=(strong_ordering lhs, strong_ordering rhs) noexcept |
508 | { return lhs.m_order != rhs.m_order; } |
509 | |
510 | friend constexpr bool operator==(strong_ordering lhs, partial_ordering rhs) noexcept |
511 | { return static_cast<partial_ordering>(lhs) == rhs; } |
512 | |
513 | friend constexpr bool operator!=(strong_ordering lhs, partial_ordering rhs) noexcept |
514 | { return static_cast<partial_ordering>(lhs) == rhs; } |
515 | |
516 | friend constexpr bool operator==(partial_ordering lhs, strong_ordering rhs) noexcept |
517 | { return lhs == static_cast<partial_ordering>(rhs); } |
518 | |
519 | friend constexpr bool operator!=(partial_ordering lhs, strong_ordering rhs) noexcept |
520 | { return lhs != static_cast<partial_ordering>(rhs); } |
521 | |
522 | friend constexpr bool operator==(strong_ordering lhs, weak_ordering rhs) noexcept |
523 | { return static_cast<weak_ordering>(lhs) == rhs; } |
524 | |
525 | friend constexpr bool operator!=(strong_ordering lhs, weak_ordering rhs) noexcept |
526 | { return static_cast<weak_ordering>(lhs) == rhs; } |
527 | |
528 | friend constexpr bool operator==(weak_ordering lhs, strong_ordering rhs) noexcept |
529 | { return lhs == static_cast<weak_ordering>(rhs); } |
530 | |
531 | friend constexpr bool operator!=(weak_ordering lhs, strong_ordering rhs) noexcept |
532 | { return lhs != static_cast<weak_ordering>(rhs); } |
533 | |
534 | #ifdef __cpp_lib_three_way_comparison |
535 | constexpr Q_IMPLICIT strong_ordering(std::strong_ordering stdorder) noexcept |
536 | { |
537 | if (stdorder == std::strong_ordering::less) |
538 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less); |
539 | else if (stdorder == std::strong_ordering::equivalent) |
540 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent); |
541 | else if (stdorder == std::strong_ordering::equal) |
542 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equal); |
543 | else if (stdorder == std::strong_ordering::greater) |
544 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater); |
545 | } |
546 | |
547 | constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept |
548 | { |
549 | static_assert(sizeof(*this) == sizeof(std::strong_ordering)); |
550 | #ifdef __cpp_lib_bit_cast |
551 | return std::bit_cast<std::strong_ordering>(*this); |
552 | #else |
553 | using O = QtPrivate::Ordering; |
554 | using R = std::strong_ordering; |
555 | switch (m_order) { |
556 | case qToUnderlying(O::Less): return R::less; |
557 | case qToUnderlying(O::Greater): return R::greater; |
558 | case qToUnderlying(O::Equal): return R::equal; |
559 | } |
560 | Q_UNREACHABLE_RETURN(R::equal); |
561 | #endif // __cpp_lib_bit_cast |
562 | } |
563 | |
564 | friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept |
565 | { return static_cast<std::strong_ordering>(lhs) == rhs; } |
566 | |
567 | friend constexpr bool operator!=(strong_ordering lhs, std::strong_ordering rhs) noexcept |
568 | { return static_cast<std::strong_ordering>(lhs) != rhs; } |
569 | |
570 | friend constexpr bool operator==(strong_ordering lhs, std::partial_ordering rhs) noexcept |
571 | { return static_cast<std::strong_ordering>(lhs) == rhs; } |
572 | |
573 | friend constexpr bool operator!=(strong_ordering lhs, std::partial_ordering rhs) noexcept |
574 | { return static_cast<std::strong_ordering>(lhs) != rhs; } |
575 | |
576 | friend constexpr bool operator==(strong_ordering lhs, std::weak_ordering rhs) noexcept |
577 | { return static_cast<std::strong_ordering>(lhs) == rhs; } |
578 | |
579 | friend constexpr bool operator!=(strong_ordering lhs, std::weak_ordering rhs) noexcept |
580 | { return static_cast<std::strong_ordering>(lhs) != rhs; } |
581 | |
582 | friend constexpr bool operator==(std::strong_ordering lhs, strong_ordering rhs) noexcept |
583 | { return lhs == static_cast<std::strong_ordering>(rhs); } |
584 | |
585 | friend constexpr bool operator!=(std::strong_ordering lhs, strong_ordering rhs) noexcept |
586 | { return lhs != static_cast<std::strong_ordering>(rhs); } |
587 | |
588 | friend constexpr bool operator==(std::partial_ordering lhs, strong_ordering rhs) noexcept |
589 | { return lhs == static_cast<std::strong_ordering>(rhs); } |
590 | |
591 | friend constexpr bool operator!=(std::partial_ordering lhs, strong_ordering rhs) noexcept |
592 | { return lhs != static_cast<std::strong_ordering>(rhs); } |
593 | |
594 | friend constexpr bool operator==(std::weak_ordering lhs, strong_ordering rhs) noexcept |
595 | { return lhs == static_cast<std::strong_ordering>(rhs); } |
596 | |
597 | friend constexpr bool operator!=(std::weak_ordering lhs, strong_ordering rhs) noexcept |
598 | { return lhs != static_cast<std::strong_ordering>(rhs); } |
599 | #endif // __cpp_lib_three_way_comparison |
600 | |
601 | private: |
602 | constexpr explicit strong_ordering(QtPrivate::Ordering order) noexcept |
603 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
604 | {} |
605 | |
606 | QT_WARNING_PUSH |
607 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903 |
608 | QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant" ) |
609 | QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant" ) |
610 | friend constexpr bool is_eq (strong_ordering o) noexcept { return o == 0; } |
611 | friend constexpr bool is_neq (strong_ordering o) noexcept { return o != 0; } |
612 | friend constexpr bool is_lt (strong_ordering o) noexcept { return o < 0; } |
613 | friend constexpr bool is_lteq(strong_ordering o) noexcept { return o <= 0; } |
614 | friend constexpr bool is_gt (strong_ordering o) noexcept { return o > 0; } |
615 | friend constexpr bool is_gteq(strong_ordering o) noexcept { return o >= 0; } |
616 | QT_WARNING_POP |
617 | |
618 | QtPrivate::CompareUnderlyingType m_order; |
619 | }; |
620 | |
621 | inline constexpr strong_ordering strong_ordering::less(QtPrivate::Ordering::Less); |
622 | inline constexpr strong_ordering strong_ordering::equivalent(QtPrivate::Ordering::Equivalent); |
623 | inline constexpr strong_ordering strong_ordering::equal(QtPrivate::Ordering::Equal); |
624 | inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::Greater); |
625 | |
626 | } // namespace Qt |
627 | |
628 | QT_BEGIN_INCLUDE_NAMESPACE |
629 | |
630 | // This is intentionally included after Qt::*_ordering types and before |
631 | // qCompareThreeWay. Do not change! |
632 | #include <QtCore/qcomparehelpers.h> |
633 | |
634 | QT_END_INCLUDE_NAMESPACE |
635 | |
636 | #if defined(Q_QDOC) |
637 | |
638 | template <typename LeftType, typename RightType> |
639 | auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs); |
640 | |
641 | #else |
642 | |
643 | template <typename LT, typename RT, |
644 | std::enable_if_t< |
645 | std::disjunction_v< |
646 | QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<LT, RT>, |
647 | QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<RT, LT>>, |
648 | bool> = true> |
649 | auto qCompareThreeWay(const LT &lhs, const RT &rhs) |
650 | noexcept(QtOrderingPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>()) |
651 | { |
652 | using Qt::compareThreeWay; |
653 | if constexpr (QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay_v<LT, RT>) { |
654 | return compareThreeWay(lhs, rhs); |
655 | } else { |
656 | const auto retval = compareThreeWay(rhs, lhs); |
657 | return QtOrderingPrivate::reversed(retval); |
658 | } |
659 | } |
660 | |
661 | #endif // defined(Q_QDOC) |
662 | |
663 | // |
664 | // Legacy QPartialOrdering |
665 | // |
666 | |
667 | namespace QtPrivate { |
668 | enum class LegacyUncomparable : CompareUnderlyingType |
669 | { |
670 | Unordered = QtPrivate::LegacyUncomparableValue |
671 | }; |
672 | } |
673 | |
674 | // [cmp.partialord] |
675 | class QPartialOrdering |
676 | { |
677 | public: |
678 | static const QPartialOrdering Less; |
679 | static const QPartialOrdering Equivalent; |
680 | static const QPartialOrdering Greater; |
681 | static const QPartialOrdering Unordered; |
682 | |
683 | static const QPartialOrdering less; |
684 | static const QPartialOrdering equivalent; |
685 | static const QPartialOrdering greater; |
686 | static const QPartialOrdering unordered; |
687 | |
688 | friend constexpr bool operator==(QPartialOrdering lhs, |
689 | QtPrivate::CompareAgainstLiteralZero) noexcept |
690 | { return lhs.isOrdered() && lhs.m_order == 0; } |
691 | |
692 | friend constexpr bool operator!=(QPartialOrdering lhs, |
693 | QtPrivate::CompareAgainstLiteralZero) noexcept |
694 | { return !lhs.isOrdered() || lhs.m_order != 0; } |
695 | |
696 | friend constexpr bool operator< (QPartialOrdering lhs, |
697 | QtPrivate::CompareAgainstLiteralZero) noexcept |
698 | { return lhs.isOrdered() && lhs.m_order < 0; } |
699 | |
700 | friend constexpr bool operator<=(QPartialOrdering lhs, |
701 | QtPrivate::CompareAgainstLiteralZero) noexcept |
702 | { return lhs.isOrdered() && lhs.m_order <= 0; } |
703 | |
704 | friend constexpr bool operator> (QPartialOrdering lhs, |
705 | QtPrivate::CompareAgainstLiteralZero) noexcept |
706 | { return lhs.isOrdered() && lhs.m_order > 0; } |
707 | |
708 | friend constexpr bool operator>=(QPartialOrdering lhs, |
709 | QtPrivate::CompareAgainstLiteralZero) noexcept |
710 | { return lhs.isOrdered() && lhs.m_order >= 0; } |
711 | |
712 | |
713 | friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, |
714 | QPartialOrdering rhs) noexcept |
715 | { return rhs.isOrdered() && 0 == rhs.m_order; } |
716 | |
717 | friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, |
718 | QPartialOrdering rhs) noexcept |
719 | { return !rhs.isOrdered() || 0 != rhs.m_order; } |
720 | |
721 | friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, |
722 | QPartialOrdering rhs) noexcept |
723 | { return rhs.isOrdered() && 0 < rhs.m_order; } |
724 | |
725 | friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, |
726 | QPartialOrdering rhs) noexcept |
727 | { return rhs.isOrdered() && 0 <= rhs.m_order; } |
728 | |
729 | friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, |
730 | QPartialOrdering rhs) noexcept |
731 | { return rhs.isOrdered() && 0 > rhs.m_order; } |
732 | |
733 | friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, |
734 | QPartialOrdering rhs) noexcept |
735 | { return rhs.isOrdered() && 0 >= rhs.m_order; } |
736 | |
737 | |
738 | #ifdef __cpp_lib_three_way_comparison |
739 | friend constexpr std::partial_ordering |
740 | operator<=>(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept |
741 | { return lhs; } // https://eel.is/c++draft/cmp.partialord#4 |
742 | |
743 | friend constexpr std::partial_ordering |
744 | operator<=>(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) noexcept |
745 | { return QtOrderingPrivate::reversed(rhs); } |
746 | #endif // __cpp_lib_three_way_comparison |
747 | |
748 | |
749 | friend constexpr bool operator==(QPartialOrdering lhs, QPartialOrdering rhs) noexcept |
750 | { return lhs.m_order == rhs.m_order; } |
751 | |
752 | friend constexpr bool operator!=(QPartialOrdering lhs, QPartialOrdering rhs) noexcept |
753 | { return lhs.m_order != rhs.m_order; } |
754 | |
755 | constexpr Q_IMPLICIT QPartialOrdering(Qt::partial_ordering order) noexcept |
756 | : m_order{} // == equivalent |
757 | { |
758 | if (order == Qt::partial_ordering::less) |
759 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less); |
760 | else if (order == Qt::partial_ordering::greater) |
761 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater); |
762 | else if (order == Qt::partial_ordering::unordered) |
763 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); |
764 | } |
765 | |
766 | constexpr Q_IMPLICIT QPartialOrdering(Qt::weak_ordering stdorder) noexcept |
767 | : QPartialOrdering(Qt::partial_ordering{stdorder}) {} |
768 | |
769 | constexpr Q_IMPLICIT QPartialOrdering(Qt::strong_ordering stdorder) noexcept |
770 | : QPartialOrdering(Qt::partial_ordering{stdorder}) {} |
771 | |
772 | constexpr Q_IMPLICIT operator Qt::partial_ordering() const noexcept |
773 | { |
774 | using O = QtPrivate::Ordering; |
775 | using U = QtPrivate::LegacyUncomparable; |
776 | using R = Qt::partial_ordering; |
777 | switch (m_order) { |
778 | case qToUnderlying(e: O::Less): return R::less; |
779 | case qToUnderlying(e: O::Greater): return R::greater; |
780 | case qToUnderlying(e: O::Equivalent): return R::equivalent; |
781 | case qToUnderlying(e: U::Unordered): return R::unordered; |
782 | } |
783 | // GCC 8.x does not treat __builtin_unreachable() as constexpr |
784 | #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900) |
785 | // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8 |
786 | Q_UNREACHABLE(); |
787 | #endif |
788 | return R::unordered; |
789 | } |
790 | |
791 | friend constexpr bool operator==(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept |
792 | { Qt::partial_ordering qt = lhs; return qt == rhs; } |
793 | |
794 | friend constexpr bool operator!=(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept |
795 | { Qt::partial_ordering qt = lhs; return qt != rhs; } |
796 | |
797 | friend constexpr bool operator==(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept |
798 | { Qt::partial_ordering qt = rhs; return lhs == qt; } |
799 | |
800 | friend constexpr bool operator!=(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept |
801 | { Qt::partial_ordering qt = rhs; return lhs != qt; } |
802 | |
803 | #ifdef __cpp_lib_three_way_comparison |
804 | constexpr Q_IMPLICIT QPartialOrdering(std::partial_ordering stdorder) noexcept |
805 | { |
806 | if (stdorder == std::partial_ordering::less) |
807 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less); |
808 | else if (stdorder == std::partial_ordering::equivalent) |
809 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent); |
810 | else if (stdorder == std::partial_ordering::greater) |
811 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater); |
812 | else if (stdorder == std::partial_ordering::unordered) |
813 | m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); |
814 | } |
815 | |
816 | constexpr Q_IMPLICIT QPartialOrdering(std::weak_ordering stdorder) noexcept |
817 | : QPartialOrdering(std::partial_ordering(stdorder)) {} |
818 | |
819 | constexpr Q_IMPLICIT QPartialOrdering(std::strong_ordering stdorder) noexcept |
820 | : QPartialOrdering(std::partial_ordering(stdorder)) {} |
821 | |
822 | constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept |
823 | { |
824 | using O = QtPrivate::Ordering; |
825 | using U = QtPrivate::LegacyUncomparable; |
826 | using R = std::partial_ordering; |
827 | switch (m_order) { |
828 | case qToUnderlying(O::Less): return R::less; |
829 | case qToUnderlying(O::Greater): return R::greater; |
830 | case qToUnderlying(O::Equivalent): return R::equivalent; |
831 | case qToUnderlying(U::Unordered): return R::unordered; |
832 | } |
833 | Q_UNREACHABLE_RETURN(R::unordered); |
834 | } |
835 | |
836 | friend constexpr bool operator==(QPartialOrdering lhs, std::partial_ordering rhs) noexcept |
837 | { return static_cast<std::partial_ordering>(lhs) == rhs; } |
838 | |
839 | friend constexpr bool operator!=(QPartialOrdering lhs, std::partial_ordering rhs) noexcept |
840 | { return static_cast<std::partial_ordering>(lhs) != rhs; } |
841 | |
842 | friend constexpr bool operator==(std::partial_ordering lhs, QPartialOrdering rhs) noexcept |
843 | { return lhs == static_cast<std::partial_ordering>(rhs); } |
844 | |
845 | friend constexpr bool operator!=(std::partial_ordering lhs, QPartialOrdering rhs) noexcept |
846 | { return lhs != static_cast<std::partial_ordering>(rhs); } |
847 | #endif // __cpp_lib_three_way_comparison |
848 | |
849 | private: |
850 | constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept |
851 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
852 | {} |
853 | constexpr explicit QPartialOrdering(QtPrivate::LegacyUncomparable order) noexcept |
854 | : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order)) |
855 | {} |
856 | |
857 | QT_WARNING_PUSH |
858 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903 |
859 | QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant" ) |
860 | QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant" ) |
861 | friend constexpr bool is_eq (QPartialOrdering o) noexcept { return o == 0; } |
862 | friend constexpr bool is_neq (QPartialOrdering o) noexcept { return o != 0; } |
863 | friend constexpr bool is_lt (QPartialOrdering o) noexcept { return o < 0; } |
864 | friend constexpr bool is_lteq(QPartialOrdering o) noexcept { return o <= 0; } |
865 | friend constexpr bool is_gt (QPartialOrdering o) noexcept { return o > 0; } |
866 | friend constexpr bool is_gteq(QPartialOrdering o) noexcept { return o >= 0; } |
867 | QT_WARNING_POP |
868 | |
869 | // instead of the exposition only is_ordered member in [cmp.partialord], |
870 | // use a private function |
871 | constexpr bool isOrdered() const noexcept |
872 | { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); } |
873 | |
874 | QtPrivate::CompareUnderlyingType m_order; |
875 | }; |
876 | |
877 | inline constexpr QPartialOrdering QPartialOrdering::Less(QtPrivate::Ordering::Less); |
878 | inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Ordering::Equivalent); |
879 | inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater); |
880 | inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::LegacyUncomparable::Unordered); |
881 | |
882 | inline constexpr QPartialOrdering QPartialOrdering::less(QtPrivate::Ordering::Less); |
883 | inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Ordering::Equivalent); |
884 | inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater); |
885 | inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered); |
886 | |
887 | QT_END_NAMESPACE |
888 | |
889 | #endif // QCOMPARE_H |
890 | |