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