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
22QT_BEGIN_NAMESPACE
23
24namespace QtPrivate {
25using CompareUnderlyingType = qint8;
26constexpr CompareUnderlyingType LegacyUncomparableValue = -127; // historic Qt value
27
28// [cmp.categories.pre] / 1
29enum class Ordering : CompareUnderlyingType
30{
31 Equal = 0,
32 Equivalent = Equal,
33 Less = -1,
34 Greater = 1
35};
36
37enum 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
51namespace QtOrderingPrivate {
52
53template <typename O>
54constexpr 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
64namespace Qt {
65
66class weak_ordering;
67class strong_ordering;
68
69class partial_ordering
70{
71public:
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
213private:
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
244inline constexpr partial_ordering partial_ordering::less(QtPrivate::Ordering::Less);
245inline constexpr partial_ordering partial_ordering::equivalent(QtPrivate::Ordering::Equivalent);
246inline constexpr partial_ordering partial_ordering::greater(QtPrivate::Ordering::Greater);
247inline constexpr partial_ordering partial_ordering::unordered(QtPrivate::Uncomparable::Unordered);
248
249class weak_ordering
250{
251public:
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
403private:
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
425inline constexpr weak_ordering weak_ordering::less(QtPrivate::Ordering::Less);
426inline constexpr weak_ordering weak_ordering::equivalent(QtPrivate::Ordering::Equivalent);
427inline constexpr weak_ordering weak_ordering::greater(QtPrivate::Ordering::Greater);
428
429class strong_ordering
430{
431public:
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
621inline constexpr strong_ordering strong_ordering::less(QtPrivate::Ordering::Less);
622inline constexpr strong_ordering strong_ordering::equivalent(QtPrivate::Ordering::Equivalent);
623inline constexpr strong_ordering strong_ordering::equal(QtPrivate::Ordering::Equal);
624inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::Greater);
625
626} // namespace Qt
627
628QT_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
634QT_END_INCLUDE_NAMESPACE
635
636#if defined(Q_QDOC)
637
638template <typename LeftType, typename RightType>
639auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs);
640
641#else
642
643template <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>
649auto 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
667namespace QtPrivate {
668enum class LegacyUncomparable : CompareUnderlyingType
669{
670 Unordered = QtPrivate::LegacyUncomparableValue
671};
672}
673
674// [cmp.partialord]
675class QPartialOrdering
676{
677public:
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
849private:
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
877inline constexpr QPartialOrdering QPartialOrdering::Less(QtPrivate::Ordering::Less);
878inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Ordering::Equivalent);
879inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater);
880inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::LegacyUncomparable::Unordered);
881
882inline constexpr QPartialOrdering QPartialOrdering::less(QtPrivate::Ordering::Less);
883inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Ordering::Equivalent);
884inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater);
885inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered);
886
887QT_END_NAMESPACE
888
889#endif // QCOMPARE_H
890

source code of qtbase/src/corelib/global/qcompare.h