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 | #include "qcompare.h" |
6 | |
7 | #ifdef __cpp_lib_bit_cast |
8 | #include <bit> |
9 | #endif |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | #ifdef __cpp_lib_three_way_comparison |
14 | #ifdef __cpp_lib_bit_cast |
15 | #define CHECK(type, flag) \ |
16 | static_assert(std::bit_cast<Qt:: type ## _ordering>(std:: type ## _ordering:: flag) \ |
17 | == Qt:: type ## _ordering :: flag); \ |
18 | static_assert(std::bit_cast<std:: type ## _ordering>(Qt:: type ## _ordering:: flag) \ |
19 | == std:: type ## _ordering :: flag) \ |
20 | /* end */ |
21 | CHECK(partial, unordered); |
22 | CHECK(partial, less); |
23 | CHECK(partial, greater); |
24 | CHECK(partial, equivalent); |
25 | CHECK(weak, less); |
26 | CHECK(weak, greater); |
27 | CHECK(weak, equivalent); |
28 | CHECK(strong, less); |
29 | CHECK(strong, greater); |
30 | CHECK(strong, equal); |
31 | CHECK(strong, equivalent); |
32 | #undef CHECK |
33 | #endif // __cpp_lib_bit_cast |
34 | #endif //__cpp_lib_three_way_comparison |
35 | |
36 | |
37 | /*! |
38 | \page comparison-types.html overview |
39 | \title Comparison types overview |
40 | \keyword three-way comparison |
41 | \inmodule QtCore |
42 | \sa Qt::strong_ordering, Qt::weak_ordering, Qt::partial_ordering |
43 | |
44 | \note Qt's comparison types provide functionality equivalent to their C++20 |
45 | standard counterparts. The only reason why they exist is to make the |
46 | functionality available in C++17 builds, too. In a C++20 build, they |
47 | implicitly convert to and from the \c std types, making them fully |
48 | interchangeable. We therefore recommended that you prefer to use the C++ |
49 | standard types in your code, if you can use C++20 in your projects already. |
50 | The Qt comparison types will be removed in Qt 7. |
51 | |
52 | Qt provides several comparison types for a \l |
53 | {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison} |
54 | {three-way comparison}, which are comparable against a \e {zero literal}. |
55 | To use these comparison types, you need to include the \c <QtCompare> |
56 | header. These comparison types are categorized based on their \e order, |
57 | which is a mathematical concept used to describe the arrangement or ranking |
58 | of elements. The following categories are provided: |
59 | |
60 | \table 100 % |
61 | \header |
62 | \li C++ type |
63 | \li Qt type |
64 | \li strict |
65 | \li total |
66 | \li Example |
67 | \row |
68 | \li \l {https://en.cppreference.com/w/cpp/utility/compare/strong_ordering} |
69 | {std::strong_ordering} |
70 | \li Qt::strong_ordering |
71 | \li yes |
72 | \li yes |
73 | \li integral types, case-sensitive strings, QDate, QTime |
74 | \row |
75 | \li \l {https://en.cppreference.com/w/cpp/utility/compare/weak_ordering} |
76 | {std::weak_ordering} |
77 | \li Qt::weak_ordering |
78 | \li no |
79 | \li yes |
80 | \li case-insensitive strings, unordered associative containers, QDateTime |
81 | \row |
82 | \li \l {https://en.cppreference.com/w/cpp/utility/compare/partial_ordering} |
83 | {std::partial_ordering} |
84 | \li Qt::partial_ordering |
85 | \li no |
86 | \li no |
87 | \li floating-point types, QOperatingSystemVersion, QVariant |
88 | \endtable |
89 | |
90 | The strongest comparison type, Qt::strong_ordering, represents a strict total |
91 | order. It requires that any two elements be comparable in a way where |
92 | equality implies substitutability. In other words, equivalent values |
93 | cannot be distinguished from each other. A practical example would be the |
94 | case-sensitive comparison of two strings. For instance, when comparing the |
95 | values \c "Qt" and \c "Qt" the result would be \l Qt::strong_ordering::equal. |
96 | Both values are indistinguishable and all deterministic operations performed |
97 | on these values would yield identical results. |
98 | |
99 | Qt::weak_ordering represents a total order. While any two values still need to |
100 | be comparable, equivalent values may be distinguishable. The canonical |
101 | example here would be the case-insensitive comparison of two strings. For |
102 | instance, when comparing the values \c "Qt" and \c "qt" both hold the same |
103 | letters but with different representations. This comparison would |
104 | result in \l Qt::weak_ordering::equivalent, but not actually \c Equal. |
105 | Another example would be QDateTime, which can represent a given instant in |
106 | time in terms of local time or any other time-zone, including UTC. The |
107 | different representations are equivalent, even though their \c time() and |
108 | sometimes \c date() may differ. |
109 | |
110 | Qt::partial_ordering represents, as the name implies, a partial ordering. It |
111 | allows for the possibility that two values may not be comparable, resulting |
112 | in an \l {Qt::partial_ordering::}{unordered} state. Additionally, equivalent |
113 | values may still be distinguishable. A practical example would be the |
114 | comparison of two floating-point values, comparing with NaN (Not-a-Number) |
115 | would yield an unordered result. Another example is the comparison of two |
116 | QOperatingSystemVersion objects. Comparing versions of two different |
117 | operating systems, such as Android and Windows, would produce an unordered |
118 | result. |
119 | |
120 | Utilizing these comparison types enhances the expressiveness of defining |
121 | relations. Furthermore, they serve as a fundamental component for |
122 | implementing three-way comparison with C++17. |
123 | */ |
124 | |
125 | /*! |
126 | \headerfile <QtCompare> |
127 | \inmodule QtCore |
128 | \title Classes and helpers for defining comparison operators |
129 | \keyword qtcompare |
130 | |
131 | \brief The <QtCompare> header file defines \c {Qt::*_ordering} types and helper |
132 | macros for defining comparison operators. |
133 | |
134 | This header introduces the \l Qt::partial_ordering, \l Qt::weak_ordering, and |
135 | \l Qt::strong_ordering types, which are Qt's C++17 backports of |
136 | \c {std::*_ordering} types. |
137 | |
138 | This header also contains functions for implementing three-way comparison |
139 | in C++17. |
140 | |
141 | The \c {Qt::compareThreeWay()} function overloads provide three-way |
142 | comparison for built-in C++ types. |
143 | |
144 | The \l qCompareThreeWay() template serves as a generic three-way comparison |
145 | implementation. It relies on \c {Qt::compareThreeWay()} and free |
146 | \c {compareThreeWay()} functions in its implementation. |
147 | */ |
148 | |
149 | /*! |
150 | \class Qt::strong_ordering |
151 | \inmodule QtCore |
152 | \inheaderfile QtCompare |
153 | \brief Qt::strong_ordering represents a comparison where equivalent values are |
154 | indistinguishable. |
155 | \sa Qt::weak_ordering, Qt::partial_ordering, {Comparison types overview} |
156 | \since 6.7 |
157 | |
158 | A value of type Qt::strong_ordering is typically returned from a three-way |
159 | comparison function. Such a function compares two objects and establishes |
160 | how they are ordered. It uses this return type to indicate that the ordering |
161 | is strict; that is, the function establishes a well-defined total order. |
162 | |
163 | Qt::strong_ordering has four values, represented by the following symbolic |
164 | constants: |
165 | |
166 | \list |
167 | \li \l less represents that the left operand is less than the right; |
168 | \li \l equal represents that the left operand is equivalent to the right; |
169 | \li \l equivalent is an alias for \c equal; |
170 | \li \l greater represents that the left operand is greater than the right. |
171 | \endlist |
172 | |
173 | Qt::strong_ordering is idiomatically used by comparing an instance against a |
174 | literal zero, for instance like this: |
175 | |
176 | \code |
177 | |
178 | // given a, b, c, d as objects of some type that allows for a 3-way compare, |
179 | // and a compare function declared as follows: |
180 | |
181 | Qt::strong_ordering compare(T lhs, T rhs); // defined out-of-line |
182 | ~~~ |
183 | |
184 | Qt::strong_ordering result = compare(a, b); |
185 | if (result < 0) { |
186 | // a is less than b |
187 | } |
188 | |
189 | if (compare(c, d) >= 0) { |
190 | // c is greater than or equal to d |
191 | } |
192 | |
193 | \endcode |
194 | */ |
195 | |
196 | /*! |
197 | \fn Qt::strong_ordering::operator Qt::partial_ordering() const |
198 | |
199 | Converts this Qt::strong_ordering value to a Qt::partial_ordering object using the |
200 | following rules: |
201 | |
202 | \list |
203 | \li \l less converts to \l {Qt::partial_ordering::less}. |
204 | \li \l equivalent converts to \l {Qt::partial_ordering::equivalent}. |
205 | \li \l equal converts to \l {Qt::partial_ordering::equivalent}. |
206 | \li \l greater converts to \l {Qt::partial_ordering::greater}. |
207 | \endlist |
208 | */ |
209 | |
210 | /*! |
211 | \fn Qt::strong_ordering::operator Qt::weak_ordering() const |
212 | |
213 | Converts this Qt::strong_ordering value to a Qt::weak_ordering object using the |
214 | following rules: |
215 | |
216 | \list |
217 | \li \l less converts to \l {Qt::weak_ordering::less}. |
218 | \li \l equivalent converts to \l {Qt::weak_ordering::equivalent}. |
219 | \li \l equal converts to \l {Qt::weak_ordering::equivalent}. |
220 | \li \l greater converts to \l {Qt::weak_ordering::greater}. |
221 | \endlist |
222 | */ |
223 | |
224 | /*! |
225 | \fn Qt::strong_ordering::strong_ordering(std::strong_ordering stdorder) |
226 | |
227 | Constructs a Qt::strong_ordering object from \a stdorder using the following rules: |
228 | |
229 | \list |
230 | \li std::strong_ordering::less converts to \l less. |
231 | \li std::strong_ordering::equivalent converts to \l equivalent. |
232 | \li std::strong_ordering::equal converts to \l equal. |
233 | \li std::strong_ordering::greater converts to \l greater. |
234 | \endlist |
235 | */ |
236 | |
237 | /*! |
238 | \fn Qt::strong_ordering::operator std::strong_ordering() const |
239 | |
240 | Converts this Qt::strong_ordering value to a std::strong_ordering object using |
241 | the following rules: |
242 | |
243 | \list |
244 | \li \l less converts to std::strong_ordering::less. |
245 | \li \l equivalent converts to std::strong_ordering::equivalent. |
246 | \li \l equal converts to std::strong_ordering::equal. |
247 | \li \l greater converts to std::strong_ordering::greater. |
248 | \endlist |
249 | */ |
250 | |
251 | /*! |
252 | \fn bool Qt::strong_ordering::operator==(Qt::strong_ordering lhs, Qt::strong_ordering rhs) |
253 | |
254 | Returns true if \a lhs and \a rhs represent the same result; |
255 | otherwise, returns false. |
256 | */ |
257 | |
258 | /*! |
259 | \fn bool Qt::strong_ordering::operator!=(Qt::strong_ordering lhs, Qt::strong_ordering rhs) |
260 | |
261 | Returns true if \a lhs and \a rhs represent different results; |
262 | otherwise, returns true. |
263 | */ |
264 | |
265 | /*! |
266 | \internal |
267 | \relates Qt::strong_ordering |
268 | \fn bool operator==(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
269 | \fn bool operator!=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
270 | \fn bool operator< (Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
271 | \fn bool operator<=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
272 | \fn bool operator> (Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
273 | \fn bool operator>=(Qt::strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
274 | |
275 | \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
276 | \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
277 | \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
278 | \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
279 | \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
280 | \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::strong_ordering rhs) |
281 | */ |
282 | |
283 | /*! |
284 | \fn Qt::strong_ordering::is_eq (Qt::strong_ordering o) |
285 | \fn Qt::strong_ordering::is_neq (Qt::strong_ordering o) |
286 | \fn Qt::strong_ordering::is_lt (Qt::strong_ordering o) |
287 | \fn Qt::strong_ordering::is_lteq(Qt::strong_ordering o) |
288 | \fn Qt::strong_ordering::is_gt (Qt::strong_ordering o) |
289 | \fn Qt::strong_ordering::is_gteq(Qt::strong_ordering o) |
290 | |
291 | //! [is_eq_table] |
292 | Converts \a o into the result of one of the six relational operators: |
293 | \table |
294 | \header \li Function \li Operation |
295 | \row \li \c{is_eq} \li \a o \c{== 0} |
296 | \row \li \c{is_neq} \li \a o \c{!= 0} |
297 | \row \li \c{is_lt} \li \a o \c{< 0} |
298 | \row \li \c{is_lteq} \li \a o \c{<= 0} |
299 | \row \li \c{is_gt} \li \a o \c{> 0} |
300 | \row \li \c{is_gteq} \li \a o \c{>= 0} |
301 | \endtable |
302 | //! [is_eq_table] |
303 | |
304 | These functions are provided for compatibility with \c{std::strong_ordering}. |
305 | */ |
306 | |
307 | /*! |
308 | \variable Qt::strong_ordering::less |
309 | |
310 | Represents the result of a comparison where the left operand is less |
311 | than the right operand. |
312 | */ |
313 | |
314 | /*! |
315 | \variable Qt::strong_ordering::equivalent |
316 | |
317 | Represents the result of a comparison where the left operand is equal |
318 | to the right operand. Same as \l {Qt::strong_ordering::equal}. |
319 | */ |
320 | |
321 | /*! |
322 | \variable Qt::strong_ordering::equal |
323 | |
324 | Represents the result of a comparison where the left operand is equal |
325 | to the right operand. Same as \l {Qt::strong_ordering::equivalent}. |
326 | */ |
327 | |
328 | /*! |
329 | \variable Qt::strong_ordering::greater |
330 | |
331 | Represents the result of a comparison where the left operand is greater |
332 | than the right operand. |
333 | */ |
334 | |
335 | /*! |
336 | \class Qt::weak_ordering |
337 | \inmodule QtCore |
338 | \inheaderfile QtCompare |
339 | \brief Qt::weak_ordering represents a comparison where equivalent values are |
340 | still distinguishable. |
341 | \sa Qt::strong_ordering, Qt::partial_ordering, {Comparison types overview} |
342 | \since 6.7 |
343 | |
344 | A value of type Qt::weak_ordering is typically returned from a three-way |
345 | comparison function. Such a function compares two objects and establishes |
346 | how they are ordered. It uses this return type to indicate that the ordering |
347 | is weak; that is, equivalent values may be distinguishable. |
348 | |
349 | Qt::weak_ordering has three values, represented by the following symbolic |
350 | constants: |
351 | |
352 | \list |
353 | \li \l less represents that the left operand is less than the right; |
354 | \li \l equivalent represents that the left operand is equivalent to the |
355 | right; |
356 | \li \l greater represents that the left operand is greater than the right, |
357 | \endlist |
358 | |
359 | Qt::weak_ordering is idiomatically used by comparing an instance against a |
360 | literal zero, for instance like this: |
361 | |
362 | \code |
363 | |
364 | // given a, b, c, d as objects of some type that allows for a 3-way compare, |
365 | // and a compare function declared as follows: |
366 | |
367 | Qt::weak_ordering compare(T lhs, T rhs); // defined out-of-line |
368 | ~~~ |
369 | |
370 | Qt::weak_ordering result = compare(a, b); |
371 | if (result < 0) { |
372 | // a is less than b |
373 | } |
374 | |
375 | if (compare(c, d) >= 0) { |
376 | // c is greater than or equivalent to d |
377 | } |
378 | |
379 | \endcode |
380 | */ |
381 | |
382 | /*! |
383 | \fn Qt::weak_ordering::operator Qt::partial_ordering() const |
384 | |
385 | Converts this Qt::weak_ordering value to a Qt::partial_ordering object using the |
386 | following rules: |
387 | |
388 | \list |
389 | \li \l less converts to \l {Qt::partial_ordering::less}. |
390 | \li \l equivalent converts to \l {Qt::partial_ordering::equivalent}. |
391 | \li \l greater converts to \l {Qt::partial_ordering::greater}. |
392 | \endlist |
393 | */ |
394 | |
395 | /*! |
396 | \fn Qt::weak_ordering::weak_ordering(std::weak_ordering stdorder) |
397 | |
398 | Constructs a Qt::weak_ordering object from \a stdorder using the following rules: |
399 | |
400 | \list |
401 | \li std::weak_ordering::less converts to \l less. |
402 | \li std::weak_ordering::equivalent converts to \l equivalent. |
403 | \li std::weak_ordering::greater converts to \l greater. |
404 | \endlist |
405 | */ |
406 | |
407 | /*! |
408 | \fn Qt::weak_ordering::operator std::weak_ordering() const |
409 | |
410 | Converts this Qt::weak_ordering value to a std::weak_ordering object using |
411 | the following rules: |
412 | |
413 | \list |
414 | \li \l less converts to std::weak_ordering::less. |
415 | \li \l equivalent converts to std::weak_ordering::equivalent. |
416 | \li \l greater converts to std::weak_ordering::greater. |
417 | \endlist |
418 | */ |
419 | |
420 | /*! |
421 | \fn bool Qt::weak_ordering::operator==(Qt::weak_ordering lhs, Qt::weak_ordering rhs) |
422 | |
423 | Return true if \a lhs and \a rhs represent the same result; |
424 | otherwise, returns false. |
425 | */ |
426 | |
427 | /*! |
428 | \fn bool Qt::weak_ordering::operator!=(Qt::weak_ordering lhs, Qt::weak_ordering rhs) |
429 | |
430 | Return true if \a lhs and \a rhs represent different results; |
431 | otherwise, returns true. |
432 | */ |
433 | |
434 | /*! |
435 | \internal |
436 | \relates Qt::weak_ordering |
437 | \fn bool operator==(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
438 | \fn bool operator!=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
439 | \fn bool operator< (Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
440 | \fn bool operator<=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
441 | \fn bool operator> (Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
442 | \fn bool operator>=(Qt::weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
443 | |
444 | \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
445 | \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
446 | \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
447 | \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
448 | \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
449 | \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::weak_ordering rhs) |
450 | */ |
451 | |
452 | /*! |
453 | \fn Qt::weak_ordering::is_eq (Qt::weak_ordering o) |
454 | \fn Qt::weak_ordering::is_neq (Qt::weak_ordering o) |
455 | \fn Qt::weak_ordering::is_lt (Qt::weak_ordering o) |
456 | \fn Qt::weak_ordering::is_lteq(Qt::weak_ordering o) |
457 | \fn Qt::weak_ordering::is_gt (Qt::weak_ordering o) |
458 | \fn Qt::weak_ordering::is_gteq(Qt::weak_ordering o) |
459 | |
460 | \include qcompare.cpp is_eq_table |
461 | |
462 | These functions are provided for compatibility with \c{std::weak_ordering}. |
463 | */ |
464 | |
465 | /*! |
466 | \variable Qt::weak_ordering::less |
467 | |
468 | Represents the result of a comparison where the left operand is less than |
469 | the right operand. |
470 | */ |
471 | |
472 | /*! |
473 | \variable Qt::weak_ordering::equivalent |
474 | |
475 | Represents the result of a comparison where the left operand is equivalent |
476 | to the right operand. |
477 | */ |
478 | |
479 | /*! |
480 | \variable Qt::weak_ordering::greater |
481 | |
482 | Represents the result of a comparison where the left operand is greater |
483 | than the right operand. |
484 | */ |
485 | |
486 | /*! |
487 | \class Qt::partial_ordering |
488 | \inmodule QtCore |
489 | \inheaderfile QtCompare |
490 | \brief Qt::partial_ordering represents the result of a comparison that allows |
491 | for unordered results. |
492 | \sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview} |
493 | \since 6.7 |
494 | |
495 | A value of type Qt::partial_ordering is typically returned from a |
496 | three-way comparison function. Such a function compares two objects, |
497 | establishing whether they are ordered and, if so, their ordering. It uses |
498 | this return type to indicate that the ordering is partial; that is, not all |
499 | pairs of values are ordered. |
500 | |
501 | Qt::partial_ordering has four values, represented by the following symbolic |
502 | constants: |
503 | |
504 | \list |
505 | \li \l less represents that the left operand is less than the right; |
506 | \li \l equivalent represents that the two operands are equivalent; |
507 | \li \l greater represents that the left operand is greater than the right; |
508 | \li \l unordered represents that the two operands are \e {not ordered}. |
509 | \endlist |
510 | |
511 | Qt::partial_ordering is idiomatically used by comparing an instance |
512 | against a literal zero, for instance like this: |
513 | |
514 | \code |
515 | |
516 | // given a, b, c, d as objects of some type that allows for a 3-way compare, |
517 | // and a compare function declared as follows: |
518 | |
519 | Qt::partial_ordering compare(T lhs, T rhs); // defined out-of-line |
520 | ~~~ |
521 | |
522 | Qt::partial_ordering result = compare(a, b); |
523 | if (result < 0) { |
524 | // a is less than b |
525 | } |
526 | |
527 | if (compare(c, d) >= 0) { |
528 | // c is greater than or equal to d |
529 | } |
530 | |
531 | \endcode |
532 | |
533 | Comparing Qt::partial_ordering::unordered against literal 0 always returns |
534 | a \c false result. |
535 | */ |
536 | |
537 | /*! |
538 | \fn Qt::partial_ordering::partial_ordering(std::partial_ordering stdorder) |
539 | |
540 | Constructs a Qt::partial_ordering object from \a stdorder using the following |
541 | rules: |
542 | |
543 | \list |
544 | \li std::partial_ordering::less converts to \l less. |
545 | \li std::partial_ordering::equivalent converts to \l equivalent. |
546 | \li std::partial_ordering::greater converts to \l greater. |
547 | \li std::partial_ordering::unordered converts to \l unordered |
548 | \endlist |
549 | */ |
550 | |
551 | /*! |
552 | \fn Qt::partial_ordering::operator std::partial_ordering() const |
553 | |
554 | Converts this Qt::partial_ordering value to a std::partial_ordering object using |
555 | the following rules: |
556 | |
557 | \list |
558 | \li \l less converts to std::partial_ordering::less. |
559 | \li \l equivalent converts to std::partial_ordering::equivalent. |
560 | \li \l greater converts to std::partial_ordering::greater. |
561 | \li \l unordered converts to std::partial_ordering::unordered. |
562 | \endlist |
563 | */ |
564 | |
565 | /*! |
566 | \fn bool Qt::partial_ordering::operator==(Qt::partial_ordering lhs, Qt::partial_ordering rhs) |
567 | |
568 | Return true if \a lhs and \a rhs represent the same result; |
569 | otherwise, returns false. |
570 | */ |
571 | |
572 | /*! |
573 | \fn bool Qt::partial_ordering::operator!=(Qt::partial_ordering lhs, Qt::partial_ordering rhs) |
574 | |
575 | Return true if \a lhs and \a rhs represent different results; |
576 | otherwise, returns true. |
577 | */ |
578 | |
579 | /*! |
580 | \internal |
581 | \relates Qt::partial_ordering |
582 | \fn bool operator==(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
583 | \fn bool operator!=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
584 | \fn bool operator< (Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
585 | \fn bool operator<=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
586 | \fn bool operator> (Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
587 | \fn bool operator>=(Qt::partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) |
588 | |
589 | \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
590 | \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
591 | \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
592 | \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
593 | \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
594 | \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, Qt::partial_ordering rhs) |
595 | */ |
596 | |
597 | /*! |
598 | \fn Qt::partial_ordering::is_eq (Qt::partial_ordering o) |
599 | \fn Qt::partial_ordering::is_neq (Qt::partial_ordering o) |
600 | \fn Qt::partial_ordering::is_lt (Qt::partial_ordering o) |
601 | \fn Qt::partial_ordering::is_lteq(Qt::partial_ordering o) |
602 | \fn Qt::partial_ordering::is_gt (Qt::partial_ordering o) |
603 | \fn Qt::partial_ordering::is_gteq(Qt::partial_ordering o) |
604 | |
605 | \include qcompare.cpp is_eq_table |
606 | |
607 | These functions are provided for compatibility with \c{std::partial_ordering}. |
608 | */ |
609 | |
610 | /*! |
611 | \variable Qt::partial_ordering::less |
612 | |
613 | Represents the result of a comparison where the left operand is less than |
614 | the right operand. |
615 | */ |
616 | |
617 | /*! |
618 | \variable Qt::partial_ordering::equivalent |
619 | |
620 | Represents the result of a comparison where the two operands are equivalent. |
621 | */ |
622 | |
623 | /*! |
624 | \variable Qt::partial_ordering::greater |
625 | |
626 | Represents the result of a comparison where the left operand is greater |
627 | than the right operand. |
628 | */ |
629 | |
630 | /*! |
631 | \variable Qt::partial_ordering::unordered |
632 | |
633 | Represents the result of a comparison where there is no ordering |
634 | relationship between the two operands. |
635 | */ |
636 | |
637 | /*! |
638 | \class QPartialOrdering |
639 | \inmodule QtCore |
640 | \brief QPartialOrdering represents the result of a comparison that allows |
641 | for unordered results. |
642 | \sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview} |
643 | \since 6.0 |
644 | |
645 | A value of type QPartialOrdering is typically returned from a |
646 | three-way comparison function. Such a function compares two objects, |
647 | establishing whether they are ordered and, if so, their ordering. It uses |
648 | this return type to indicate that the ordering is partial; that is, not all |
649 | pairs of values are ordered. |
650 | |
651 | QPartialOrdering has four values, represented by the following symbolic |
652 | constants: |
653 | |
654 | \list |
655 | \li \l less represents that the left operand is less than the right; |
656 | \li \l equivalent represents that the two operands are equivalent; |
657 | \li \l greater represents that the left operand is greater than the right; |
658 | \li \l unordered represents that the two operands are \e {not ordered}. |
659 | \endlist |
660 | |
661 | QPartialOrdering is idiomatically used by comparing an instance |
662 | against a literal zero, for instance like this: |
663 | |
664 | \code |
665 | |
666 | // given a, b, c, d as objects of some type that allows for a 3-way compare, |
667 | // and a compare function declared as follows: |
668 | |
669 | QPartialOrdering compare(T lhs, T rhs); // defined out-of-line |
670 | ~~~ |
671 | |
672 | QPartialOrdering result = compare(a, b); |
673 | if (result < 0) { |
674 | // a is less than b |
675 | } |
676 | |
677 | if (compare(c, d) >= 0) { |
678 | // c is greater than or equal to d |
679 | } |
680 | |
681 | \endcode |
682 | |
683 | Comparing QPartialOrdering::unordered against literal 0 always returns |
684 | a \c false result. |
685 | */ |
686 | |
687 | /*! |
688 | \fn QPartialOrdering::QPartialOrdering(std::partial_ordering stdorder) |
689 | |
690 | Constructs a QPartialOrdering object from \a stdorder using the following |
691 | rules: |
692 | |
693 | \list |
694 | \li std::partial_ordering::less converts to \l less. |
695 | \li std::partial_ordering::equivalent converts to \l equivalent. |
696 | \li std::partial_ordering::greater converts to \l greater. |
697 | \li std::partial_ordering::unordered converts to \l unordered |
698 | \endlist |
699 | */ |
700 | |
701 | /*! |
702 | \fn QPartialOrdering::operator std::partial_ordering() const |
703 | |
704 | Converts this QPartialOrdering value to a std::partial_ordering object using |
705 | the following rules: |
706 | |
707 | \list |
708 | \li \l less converts to std::partial_ordering::less. |
709 | \li \l equivalent converts to std::partial_ordering::equivalent. |
710 | \li \l greater converts to std::partial_ordering::greater. |
711 | \li \l unordered converts to std::partial_ordering::unordered. |
712 | \endlist |
713 | */ |
714 | |
715 | /*! |
716 | \fn bool QPartialOrdering::operator==(QPartialOrdering lhs, QPartialOrdering rhs) |
717 | |
718 | Return true if \a lhs and \a rhs represent the same result; |
719 | otherwise, returns false. |
720 | */ |
721 | |
722 | /*! |
723 | \fn bool QPartialOrdering::operator!=(QPartialOrdering lhs, QPartialOrdering rhs) |
724 | |
725 | Return true if \a lhs and \a rhs represent different results; |
726 | otherwise, returns true. |
727 | */ |
728 | |
729 | /*! |
730 | \internal |
731 | \relates QPartialOrdering |
732 | \fn bool operator==(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
733 | \fn bool operator!=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
734 | \fn bool operator< (QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
735 | \fn bool operator<=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
736 | \fn bool operator> (QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
737 | \fn bool operator>=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) |
738 | |
739 | \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
740 | \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
741 | \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
742 | \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
743 | \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
744 | \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) |
745 | */ |
746 | |
747 | /*! |
748 | \fn QPartialOrdering::is_eq (QPartialOrdering o) |
749 | \fn QPartialOrdering::is_neq (QPartialOrdering o) |
750 | \fn QPartialOrdering::is_lt (QPartialOrdering o) |
751 | \fn QPartialOrdering::is_lteq(QPartialOrdering o) |
752 | \fn QPartialOrdering::is_gt (QPartialOrdering o) |
753 | \fn QPartialOrdering::is_gteq(QPartialOrdering o) |
754 | |
755 | \since 6.7 |
756 | \include qcompare.cpp is_eq_table |
757 | |
758 | These functions are provided for compatibility with \c{std::partial_ordering}. |
759 | */ |
760 | |
761 | /*! |
762 | \variable QPartialOrdering::less |
763 | |
764 | Represents the result of a comparison where the left operand is less than |
765 | the right operand. |
766 | */ |
767 | |
768 | /*! |
769 | \variable QPartialOrdering::equivalent |
770 | |
771 | Represents the result of a comparison where the two operands are equivalent. |
772 | */ |
773 | |
774 | /*! |
775 | \variable QPartialOrdering::greater |
776 | |
777 | Represents the result of a comparison where the left operand is greater |
778 | than the right operand. |
779 | */ |
780 | |
781 | /*! |
782 | \variable QPartialOrdering::unordered |
783 | |
784 | Represents the result of a comparison where there is no ordering |
785 | relationship between the two operands. |
786 | */ |
787 | |
788 | /*! |
789 | \variable QPartialOrdering::Less |
790 | |
791 | Represents the result of a comparison where the left operand is less than |
792 | the right operand. |
793 | */ |
794 | |
795 | /*! |
796 | \variable QPartialOrdering::Equivalent |
797 | |
798 | Represents the result of a comparison where the two operands are equivalent. |
799 | */ |
800 | |
801 | /*! |
802 | \variable QPartialOrdering::Greater |
803 | |
804 | Represents the result of a comparison where the left operand is greater |
805 | than the right operand. |
806 | */ |
807 | |
808 | /*! |
809 | \variable QPartialOrdering::Unordered |
810 | |
811 | Represents the result of a comparison where there is no ordering |
812 | relationship between the two operands. |
813 | */ |
814 | |
815 | /*! |
816 | \internal |
817 | \macro Q_DECLARE_EQUALITY_COMPARABLE(Type) |
818 | \macro Q_DECLARE_EQUALITY_COMPARABLE(LeftType, RightType) |
819 | \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(Type) |
820 | \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(LeftType, RightType) |
821 | \since 6.7 |
822 | \relates <QtCompare> |
823 | |
824 | These macros are used to generate \c {operator==()} and \c {operator!=()}. |
825 | |
826 | In C++17 mode, the mixed-type overloads also generate the reversed |
827 | operators. |
828 | |
829 | In C++20 mode, only \c {operator==()} is defined. \c {operator!=()}, |
830 | as well as the reversed operators for mixed-type comparison, are synthesized |
831 | by the compiler. |
832 | |
833 | The operators are implemented in terms of a helper function |
834 | \c {comparesEqual()}. |
835 | It's the user's responsibility to declare and define this function. |
836 | |
837 | Consider the following example of a comparison operators declaration: |
838 | |
839 | \code |
840 | class MyClass { |
841 | ... |
842 | private: |
843 | friend bool comparesEqual(const MyClass &, const MyClass &) noexcept; |
844 | Q_DECLARE_EQUALITY_COMPARABLE(MyClass) |
845 | }; |
846 | \endcode |
847 | |
848 | When compiled with C++17, the macro will expand into the following code: |
849 | |
850 | \code |
851 | friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept |
852 | { |
853 | // inline implementation which uses comparesEqual() |
854 | } |
855 | friend bool operator!=(const MyClass &lhs, const MyClass &rhs) noexcept |
856 | { |
857 | // inline implementation which uses comparesEqual() |
858 | } |
859 | \endcode |
860 | |
861 | When compiled with C++20, the macro will expand only into \c {operator==()}: |
862 | |
863 | \code |
864 | friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept |
865 | { |
866 | // inline implementation which uses comparesEqual() |
867 | } |
868 | \endcode |
869 | |
870 | The \c {*_LITERAL_TYPE} versions of the macros are used to generate |
871 | \c constexpr operators. This means that the helper \c {comparesEqual()} |
872 | function must also be \c constexpr. |
873 | |
874 | Consider the following example of a mixed-type \c constexpr comparison |
875 | operators declaration: |
876 | |
877 | \code |
878 | class MyClass { |
879 | ... |
880 | private: |
881 | friend constexpr bool comparesEqual(const MyClass &, int) noexcept; |
882 | Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(MyClass, int) |
883 | }; |
884 | \endcode |
885 | |
886 | When compiled with C++17, the macro will expand into the following code: |
887 | |
888 | \code |
889 | friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept |
890 | { |
891 | // inline implementation which uses comparesEqual() |
892 | } |
893 | friend constexpr bool operator!=(const MyClass &lhs, int rhs) noexcept |
894 | { |
895 | // inline implementation which uses comparesEqual() |
896 | } |
897 | friend constexpr bool operator==(int lhs, const MyClass &rhs) noexcept |
898 | { |
899 | // inline implementation which uses comparesEqual() |
900 | } |
901 | friend constexpr bool operator!=(int lhs, const MyClass &rhs) noexcept |
902 | { |
903 | // inline implementation which uses comparesEqual() |
904 | } |
905 | \endcode |
906 | |
907 | When compiled with C++20, the macro expands only into \c {operator==()}: |
908 | |
909 | \code |
910 | friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept |
911 | { |
912 | // inline implementation which uses comparesEqual() |
913 | } |
914 | \endcode |
915 | |
916 | //! [noexcept-requirement-desc] |
917 | These macros generate \c {noexcept} relational operators, and so they check |
918 | that the helper functions are \c {noexcept}. |
919 | Use the \c {_NON_NOEXCEPT} versions of the macros if the relational |
920 | operators of your class cannot be \c {noexcept}. |
921 | //! [noexcept-requirement-desc] |
922 | */ |
923 | |
924 | /*! |
925 | \internal |
926 | \macro Q_DECLARE_PARTIALLY_ORDERED(Type) |
927 | \macro Q_DECLARE_PARTIALLY_ORDERED(LeftType, RightType) |
928 | \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(Type) |
929 | \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(LeftType, RightType) |
930 | \since 6.7 |
931 | \relates <QtCompare> |
932 | |
933 | These macros are used to generate all six relational operators. |
934 | The operators represent |
935 | \l {https://en.cppreference.com/w/cpp/utility/compare/partial_ordering} |
936 | {partial ordering}. |
937 | |
938 | These macros use respective overloads of the |
939 | \l {Q_DECLARE_EQUALITY_COMPARABLE} macro to generate \c {operator==()} and |
940 | \c {operator!=()}, and also generate the four relational operators: |
941 | \c {operator<()}, \c {operator>()}, \c {operator<=()}, and \c {operator>()}. |
942 | |
943 | In C++17 mode, the mixed-type overloads also generate the reversed |
944 | operators. |
945 | |
946 | In C++20 mode, only \c {operator==()} and \c {operator<=>()} are defined. |
947 | Other operators, as well as the reversed operators for mixed-type |
948 | comparison, are synthesized by the compiler. |
949 | |
950 | The (in)equality operators are implemented in terms of a helper function |
951 | \c {comparesEqual()}. The other relational operators are implemented in |
952 | terms of a helper function \c {compareThreeWay()}. |
953 | The \c {compareThreeWay()} function \e must return an object of type |
954 | \l Qt::partial_ordering. It's the user's responsibility to declare and define |
955 | both helper functions. |
956 | |
957 | Consider the following example of a comparison operators declaration: |
958 | |
959 | \code |
960 | class MyClass { |
961 | ... |
962 | private: |
963 | friend bool comparesEqual(const MyClass &, const MyClass &) noexcept; |
964 | friend Qt::partial_ordering compareThreeWay(const MyClass &, const MyClass &) noexcept; |
965 | Q_DECLARE_PARTIALLY_ORDERED(MyClass) |
966 | }; |
967 | \endcode |
968 | |
969 | When compiled with C++17, the macro will expand into the following code: |
970 | |
971 | \code |
972 | // operator==() and operator!=() are generated from |
973 | // Q_DECLARE_EQUALITY_COMPARABLE |
974 | friend bool operator<(const MyClass &lhs, const MyClass &rhs) noexcept |
975 | { |
976 | // inline implementation which uses compareThreeWay() |
977 | } |
978 | friend bool operator>(const MyClass &lhs, const MyClass &rhs) noexcept |
979 | { |
980 | // inline implementation which uses compareThreeWay() |
981 | } |
982 | friend bool operator<=(const MyClass &lhs, const MyClass &rhs) noexcept |
983 | { |
984 | // inline implementation which uses compareThreeWay() |
985 | } |
986 | friend bool operator>=(const MyClass &lhs, const MyClass &rhs) noexcept |
987 | { |
988 | // inline implementation which uses compareThreeWay() |
989 | } |
990 | \endcode |
991 | |
992 | When compiled with C++20, the macro will expand into \c {operator==()} and |
993 | \c {operator<=>()}: |
994 | |
995 | \code |
996 | friend bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept |
997 | { |
998 | // inline implementation which uses comparesEqual() |
999 | } |
1000 | friend std::partial_ordering |
1001 | operator<=>(const MyClass &lhs, const MyClass &rhs) noexcept |
1002 | { |
1003 | // inline implementation which uses compareThreeWay() |
1004 | } |
1005 | \endcode |
1006 | |
1007 | The \c {*_LITERAL_TYPE} versions of the macros are used to generate |
1008 | \c constexpr operators. This means that the helper \c {comparesEqual()} and |
1009 | \c {compareThreeWay()} functions must also be \c constexpr. |
1010 | |
1011 | Consider the following example of a mixed-type \c constexpr comparison |
1012 | operators declaration: |
1013 | |
1014 | \code |
1015 | class MyClass { |
1016 | ... |
1017 | private: |
1018 | friend constexpr bool comparesEqual(const MyClass &, int) noexcept; |
1019 | friend constexpr Qt::partial_ordering compareThreeWay(const MyClass &, int) noexcept; |
1020 | Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(MyClass, int) |
1021 | }; |
1022 | \endcode |
1023 | |
1024 | When compiled with C++17, the macro will expand into the following code: |
1025 | |
1026 | \code |
1027 | // operator==(), operator!=(), and their reversed versions are generated |
1028 | // from Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE |
1029 | friend constexpr bool operator<(const MyClass &lhs, int rhs) noexcept |
1030 | { |
1031 | // inline implementation which uses compareThreeWay() |
1032 | } |
1033 | friend constexpr bool operator>(const MyClass &lhs, int rhs) noexcept |
1034 | { |
1035 | // inline implementation which uses compareThreeWay() |
1036 | } |
1037 | friend constexpr bool operator<=(const MyClass &lhs, int rhs) noexcept |
1038 | { |
1039 | // inline implementation which uses compareThreeWay() |
1040 | } |
1041 | friend constexpr bool operator>=(const MyClass &lhs, int rhs) noexcept |
1042 | { |
1043 | // inline implementation which uses compareThreeWay() |
1044 | } |
1045 | friend constexpr bool operator<(int lhs, const MyClass &rhs) noexcept |
1046 | { |
1047 | // inline implementation which uses compareThreeWay() |
1048 | } |
1049 | friend constexpr bool operator>(int lhs, const MyClass &rhs) noexcept |
1050 | { |
1051 | // inline implementation which uses compareThreeWay() |
1052 | } |
1053 | friend constexpr bool operator<=(int lhs, const MyClass &rhs) noexcept |
1054 | { |
1055 | // inline implementation which uses compareThreeWay() |
1056 | } |
1057 | friend constexpr bool operator>=(int lhs, const MyClass &rhs) noexcept |
1058 | { |
1059 | // inline implementation which uses compareThreeWay() |
1060 | } |
1061 | \endcode |
1062 | |
1063 | When compiled with C++20, the macro will expand into \c {operator==()} and |
1064 | \c {operator<=>()}: |
1065 | |
1066 | \code |
1067 | friend constexpr bool operator==(const MyClass &lhs, int rhs) noexcept |
1068 | { |
1069 | // inline implementation which uses comparesEqual() |
1070 | } |
1071 | friend constexpr std::partial_ordering |
1072 | operator<=>(const MyClass &lhs, int rhs) noexcept |
1073 | { |
1074 | // inline implementation which uses compareThreeWay() |
1075 | } |
1076 | \endcode |
1077 | |
1078 | \include qcompare.cpp noexcept-requirement-desc |
1079 | |
1080 | \sa Q_DECLARE_EQUALITY_COMPARABLE, Q_DECLARE_WEAKLY_ORDERED, |
1081 | Q_DECLARE_STRONGLY_ORDERED |
1082 | */ |
1083 | |
1084 | /*! |
1085 | \internal |
1086 | \macro Q_DECLARE_WEAKLY_ORDERED(Type) |
1087 | \macro Q_DECLARE_WEAKLY_ORDERED(LeftType, RightType) |
1088 | \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(Type) |
1089 | \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(LeftType, RightType) |
1090 | \since 6.7 |
1091 | \relates <QtCompare> |
1092 | |
1093 | These macros behave similarly to the |
1094 | \l {Q_DECLARE_PARTIALLY_ORDERED} overloads, but represent |
1095 | \l {https://en.cppreference.com/w/cpp/utility/compare/weak_ordering} |
1096 | {weak ordering}. |
1097 | |
1098 | The (in)equality operators are implemented in terms of a helper function |
1099 | \c {comparesEqual()}. The other relational operators are implemented in |
1100 | terms of a helper function \c {compareThreeWay()}. |
1101 | The \c {compareThreeWay()} function \e must return an object of type |
1102 | \l Qt::weak_ordering. It's the user's responsibility to declare and define both |
1103 | helper functions. |
1104 | |
1105 | The \c {*_LITERAL_TYPE} overloads are used to generate \c constexpr |
1106 | operators. This means that the helper \c {comparesEqual()} and |
1107 | \c {compareThreeWay()} functions must also be \c constexpr. |
1108 | |
1109 | \include qcompare.cpp noexcept-requirement-desc |
1110 | |
1111 | See \l {Q_DECLARE_PARTIALLY_ORDERED} for usage examples. |
1112 | |
1113 | \sa Q_DECLARE_PARTIALLY_ORDERED, Q_DECLARE_STRONGLY_ORDERED, |
1114 | Q_DECLARE_EQUALITY_COMPARABLE |
1115 | */ |
1116 | |
1117 | /*! |
1118 | \internal |
1119 | \macro Q_DECLARE_STRONGLY_ORDERED(Type) |
1120 | \macro Q_DECLARE_STRONGLY_ORDERED(LeftType, RightType) |
1121 | \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(Type) |
1122 | \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(LeftType, RightType) |
1123 | \since 6.7 |
1124 | \relates <QtCompare> |
1125 | |
1126 | These macros behave similarly to the |
1127 | \l {Q_DECLARE_PARTIALLY_ORDERED} overloads, but represent |
1128 | \l {https://en.cppreference.com/w/cpp/utility/compare/strong_ordering} |
1129 | {strong ordering}. |
1130 | |
1131 | The (in)equality operators are implemented in terms of a helper function |
1132 | \c {comparesEqual()}. The other relational operators are implemented in |
1133 | terms of a helper function \c {compareThreeWay()}. |
1134 | The \c {compareThreeWay()} function \e must return an object of type |
1135 | \l Qt::strong_ordering. It's the user's responsibility to declare and define |
1136 | both helper functions. |
1137 | |
1138 | The \c {*_LITERAL_TYPE} overloads are used to generate \c constexpr |
1139 | operators. This means that the helper \c {comparesEqual()} and |
1140 | \c {compareThreeWay()} functions must also be \c constexpr. |
1141 | |
1142 | \include qcompare.cpp noexcept-requirement-desc |
1143 | |
1144 | See \l {Q_DECLARE_PARTIALLY_ORDERED} for usage examples. |
1145 | |
1146 | \sa Q_DECLARE_PARTIALLY_ORDERED, Q_DECLARE_WEAKLY_ORDERED, |
1147 | Q_DECLARE_EQUALITY_COMPARABLE |
1148 | */ |
1149 | |
1150 | /*! |
1151 | \internal |
1152 | \macro Q_DECLARE_EQUALITY_COMPARABLE(LeftType, RightType, Attributes) |
1153 | \macro Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(LeftType, RightType, Attributes) |
1154 | \macro Q_DECLARE_PARTIALLY_ORDERED(LeftType, RightType, Attributes) |
1155 | \macro Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes) |
1156 | \macro Q_DECLARE_WEAKLY_ORDERED(LeftType, RightType, Attributes) |
1157 | \macro Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes) |
1158 | \macro Q_DECLARE_STRONGLY_ORDERED(LeftType, RightType, Attributes) |
1159 | \macro Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(LeftType, RightType, Attributes) |
1160 | \since 6.8 |
1161 | \relates <QtCompare> |
1162 | |
1163 | These macros behave like their two-argument versions, but allow |
1164 | specification of C++ attributes to add before every generated relational |
1165 | operator. |
1166 | |
1167 | As an example, the \c Attributes parameter can be used in Qt to pass |
1168 | the \c QT_ASCII_CAST_WARN marco (whose expansion can mark the function as |
1169 | deprecated) when implementing comparison of encoding-aware string types |
1170 | with C-style strings or byte arrays. |
1171 | |
1172 | \include qcompare.cpp noexcept-requirement-desc |
1173 | */ |
1174 | |
1175 | /*! |
1176 | \internal |
1177 | \macro Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(Type) |
1178 | \macro Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(LeftType, RightType) |
1179 | \macro Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(LeftType, RightType, Attributes) |
1180 | \macro Q_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT(Type) |
1181 | \macro Q_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT(LeftType, RightType) |
1182 | \macro Q_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT(LeftType, RightType, Attributes) |
1183 | \macro Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(Type) |
1184 | \macro Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(LeftType, RightType) |
1185 | \macro Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(LeftType, RightType, Attributes) |
1186 | \macro Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(Type) |
1187 | \macro Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(LeftType, RightType) |
1188 | \macro Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(LeftType, RightType, Attributes) |
1189 | \since 6.8 |
1190 | \relates <QtCompare> |
1191 | |
1192 | These macros behave like their versions without the \c {_NON_NOEXCEPT} |
1193 | suffix, but should be used when the relational operators cannot be |
1194 | \c {noexcept}. |
1195 | */ |
1196 | |
1197 | /*! |
1198 | \fn template <typename LeftInt, typename RightInt, Qt::if_integral<LeftInt> = true, Qt::if_integral<RightInt> = true> auto Qt::compareThreeWay(LeftInt lhs, RightInt rhs) |
1199 | \since 6.7 |
1200 | \relates <QtCompare> |
1201 | \overload |
1202 | |
1203 | Implements three-way comparison of integral types. |
1204 | |
1205 | \note This function participates in overload resolution only if both |
1206 | \c LeftInt and \c RightInt are built-in integral types. |
1207 | |
1208 | Returns \c {lhs <=> rhs}, provided \c LeftInt and \c RightInt are built-in |
1209 | integral types. Unlike \c {operator<=>()}, this function template is also |
1210 | available in C++17. See |
1211 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison} |
1212 | {cppreference} for more details. |
1213 | |
1214 | This function can also be used in custom \c {compareThreeWay()} functions, |
1215 | when ordering members of a custom class represented by built-in types: |
1216 | |
1217 | \code |
1218 | class MyClass { |
1219 | public: |
1220 | ... |
1221 | private: |
1222 | int value; |
1223 | ... |
1224 | friend Qt::strong_ordering |
1225 | compareThreeWay(const MyClass &lhs, const MyClass &rhs) noexcept |
1226 | { return Qt::compareThreeWay(lhs.value, rhs.value); } |
1227 | Q_DECLARE_STRONGLY_ORDERED(MyClass) |
1228 | }; |
1229 | \endcode |
1230 | |
1231 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1232 | between \a lhs and \a rhs. |
1233 | */ |
1234 | |
1235 | /*! |
1236 | \fn template <typename LeftFloat, typename RightFloat, Qt::if_floating_point<LeftFloat> = true, Qt::if_floating_point<RightFloat> = true> auto Qt::compareThreeWay(LeftFloat lhs, RightFloat rhs) |
1237 | \since 6.7 |
1238 | \relates <QtCompare> |
1239 | \overload |
1240 | |
1241 | Implements three-way comparison of floating point types. |
1242 | |
1243 | \note This function participates in overload resolution only if both |
1244 | \c LeftFloat and \c RightFloat are built-in floating-point types. |
1245 | |
1246 | Returns \c {lhs <=> rhs}, provided \c LeftFloat and \c RightFloat are |
1247 | built-in floating-point types. Unlike \c {operator<=>()}, this function |
1248 | template is also available in C++17. See |
1249 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Three-way_comparison} |
1250 | {cppreference} for more details. |
1251 | |
1252 | This function can also be used in custom \c {compareThreeWay()} functions, |
1253 | when ordering members of a custom class represented by built-in types: |
1254 | |
1255 | \code |
1256 | class MyClass { |
1257 | public: |
1258 | ... |
1259 | private: |
1260 | double value; |
1261 | ... |
1262 | friend Qt::partial_ordering |
1263 | compareThreeWay(const MyClass &lhs, const MyClass &rhs) noexcept |
1264 | { return Qt::compareThreeWay(lhs.value, rhs.value); } |
1265 | Q_DECLARE_PARTIALLY_ORDERED(MyClass) |
1266 | }; |
1267 | \endcode |
1268 | |
1269 | Returns an instance of \l Qt::partial_ordering that represents the relation |
1270 | between \a lhs and \a rhs. If \a lhs or \a rhs is not a number (NaN), |
1271 | \l Qt::partial_ordering::unordered is returned. |
1272 | */ |
1273 | |
1274 | /*! |
1275 | \fn template <typename IntType, typename FloatType, Qt::if_integral<IntType> = true, Qt::if_floating_point<FloatType> = true> auto Qt::compareThreeWay(IntType lhs, FloatType rhs) |
1276 | \since 6.7 |
1277 | \relates <QtCompare> |
1278 | \overload |
1279 | |
1280 | Implements three-way comparison of integral and floating point types. |
1281 | |
1282 | \note This function participates in overload resolution only if \c IntType |
1283 | is a built-in integral type and \c FloatType is a built-in floating-point |
1284 | type. |
1285 | |
1286 | This function converts \a lhs to \c FloatType and calls the overload for |
1287 | floating-point types. |
1288 | |
1289 | Returns an instance of \l Qt::partial_ordering that represents the relation |
1290 | between \a lhs and \a rhs. If \a rhs is not a number (NaN), |
1291 | \l Qt::partial_ordering::unordered is returned. |
1292 | */ |
1293 | |
1294 | /*! |
1295 | \fn template <typename FloatType, typename IntType, Qt::if_floating_point<FloatType> = true, Qt::if_integral<IntType> = true> auto Qt::compareThreeWay(FloatType lhs, IntType rhs) |
1296 | \since 6.7 |
1297 | \relates <QtCompare> |
1298 | \overload |
1299 | |
1300 | Implements three-way comparison of floating point and integral types. |
1301 | |
1302 | \note This function participates in overload resolution only if \c FloatType |
1303 | is a built-in floating-point type and \c IntType is a built-in integral |
1304 | type. |
1305 | |
1306 | This function converts \a rhs to \c FloatType and calls the overload for |
1307 | floating-point types. |
1308 | |
1309 | Returns an instance of \l Qt::partial_ordering that represents the relation |
1310 | between \a lhs and \a rhs. If \a lhs is not a number (NaN), |
1311 | \l Qt::partial_ordering::unordered is returned. |
1312 | */ |
1313 | |
1314 | #if QT_DEPRECATED_SINCE(6, 8) |
1315 | /*! |
1316 | \fn template <typename LeftType, typename RightType, Qt::if_compatible_pointers<LeftType, RightType> = true> Qt::compareThreeWay(const LeftType *lhs, const RightType *rhs) |
1317 | \since 6.7 |
1318 | \deprecated [6.8] Wrap the pointers into Qt::totally_ordered_wrapper and |
1319 | use the respective Qt::compareThreeWay() overload instead. |
1320 | \relates <QtCompare> |
1321 | \overload |
1322 | |
1323 | Implements three-way comparison of pointers. |
1324 | |
1325 | \note This function participates in overload resolution if \c LeftType and |
1326 | \c RightType are the same type, or base and derived types. It is also used |
1327 | to compare any pointer to \c {std::nullptr_t}. |
1328 | |
1329 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1330 | between \a lhs and \a rhs. |
1331 | */ |
1332 | #endif // QT_DEPRECATED_SINCE(6, 8) |
1333 | |
1334 | /*! |
1335 | \fn template <class Enum, Qt::if_enum<Enum> = true> Qt::compareThreeWay(Enum lhs, Enum rhs) |
1336 | \since 6.7 |
1337 | \relates <QtCompare> |
1338 | \overload |
1339 | |
1340 | Implements three-way comparison of enum types. |
1341 | |
1342 | \note This function participates in overload resolution only if \c Enum |
1343 | is an enum type. |
1344 | |
1345 | This function converts \c Enum to its underlying type and calls the |
1346 | overload for integral types. |
1347 | |
1348 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1349 | between \a lhs and \a rhs. |
1350 | */ |
1351 | |
1352 | /*! |
1353 | \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<U*> rhs) |
1354 | \since 6.8 |
1355 | \relates <QtCompare> |
1356 | \overload |
1357 | |
1358 | Implements three-way comparison of pointers that are wrapped into |
1359 | \l Qt::totally_ordered_wrapper. Uses |
1360 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} |
1361 | {strict total order over pointers} when doing the comparison. |
1362 | |
1363 | \note This function participates in overload resolution if \c T and \c U |
1364 | are the same type, or base and derived types. |
1365 | |
1366 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1367 | between \a lhs and \a rhs. |
1368 | */ |
1369 | |
1370 | /*! |
1371 | \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, U *rhs) |
1372 | \since 6.8 |
1373 | \relates <QtCompare> |
1374 | \overload |
1375 | |
1376 | Implements three-way comparison of a pointer wrapped into |
1377 | \l Qt::totally_ordered_wrapper with a normal pointer. Uses |
1378 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} |
1379 | {strict total order over pointers} when doing the comparison. |
1380 | |
1381 | \note This function participates in overload resolution if \c T and \c U |
1382 | are the same type, or base and derived types. |
1383 | |
1384 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1385 | between \a lhs and \a rhs. |
1386 | */ |
1387 | |
1388 | /*! |
1389 | \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(U *lhs, Qt::totally_ordered_wrapper<T*> rhs) |
1390 | \since 6.8 |
1391 | \relates <QtCompare> |
1392 | \overload |
1393 | |
1394 | Implements three-way comparison of a normal pointer with a pointer wrapped |
1395 | into \l Qt::totally_ordered_wrapper. Uses |
1396 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} |
1397 | {strict total order over pointers} when doing the comparison. |
1398 | |
1399 | \note This function participates in overload resolution if \c T and \c U |
1400 | are the same type, or base and derived types. |
1401 | |
1402 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1403 | between \a lhs and \a rhs. |
1404 | */ |
1405 | |
1406 | /*! |
1407 | \fn template <typename T> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) |
1408 | \since 6.8 |
1409 | \relates <QtCompare> |
1410 | \overload |
1411 | |
1412 | Implements three-way comparison of a pointer wrapped into |
1413 | \l Qt::totally_ordered_wrapper with \c {std::nullptr_t}. |
1414 | |
1415 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1416 | between \a lhs and \a rhs. |
1417 | */ |
1418 | |
1419 | /*! |
1420 | \fn template <typename T> Qt::compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) |
1421 | \since 6.8 |
1422 | \relates <QtCompare> |
1423 | \overload |
1424 | |
1425 | Implements three-way comparison of \c {std::nullptr_t} with a pointer |
1426 | wrapped into \l Qt::totally_ordered_wrapper. |
1427 | |
1428 | Returns an instance of \l Qt::strong_ordering that represents the relation |
1429 | between \a lhs and \a rhs. |
1430 | */ |
1431 | |
1432 | /*! |
1433 | \fn template <typename LeftType, typename RightType> qCompareThreeWay(const LeftType &lhs, const RightType &rhs) |
1434 | \since 6.7 |
1435 | \relates <QtCompare> |
1436 | |
1437 | Performs the three-way comparison on \a lhs and \a rhs and returns one of |
1438 | the Qt ordering types as a result. This function is available for both |
1439 | C++17 and C++20. |
1440 | |
1441 | The actual returned type depends on \c LeftType and \c RightType. |
1442 | |
1443 | \note This function template is only available when \c {compareThreeWay()} |
1444 | is implemented for the \c {(LeftType, RightType)} pair or the reversed |
1445 | \c {(RightType, LeftType)} pair. |
1446 | |
1447 | This method is equivalent to |
1448 | |
1449 | \code |
1450 | using Qt::compareThreeWay; |
1451 | return compareThreeWay(lhs, rhs); |
1452 | \endcode |
1453 | |
1454 | where \c {Qt::compareThreeWay} is the Qt implementation of three-way |
1455 | comparison for built-in types. |
1456 | |
1457 | The free \c {compareThreeWay} functions should provide three-way comparison |
1458 | for custom types. The functions should return one of the Qt ordering types. |
1459 | |
1460 | Qt provides \c {compareThreeWay} implementation for some of its types. |
1461 | |
1462 | \note \b {Do not} re-implement \c {compareThreeWay()} for Qt types, as more |
1463 | Qt types will get support for it in future Qt releases. |
1464 | |
1465 | Use this function primarly in generic code, when you know nothing about |
1466 | \c LeftType and \c RightType. |
1467 | |
1468 | If you know the types, use |
1469 | |
1470 | \list |
1471 | \li \c {Qt::compareThreeWay} for built-in types |
1472 | \li \c {compareThreeWay} for custom types |
1473 | \endlist |
1474 | |
1475 | Use \c {operator<=>()} directly in code that will only be compiled with |
1476 | C++20 or later. |
1477 | |
1478 | \sa Qt::partial_ordering, Qt::weak_ordering, Qt::strong_ordering |
1479 | */ |
1480 | |
1481 | /*! |
1482 | \class Qt::totally_ordered_wrapper |
1483 | \inmodule QtCore |
1484 | \inheaderfile QtCompare |
1485 | \brief Qt::totally_ordered_wrapper is a wrapper type that provides strict |
1486 | total order for the wrapped types. |
1487 | \since 6.8 |
1488 | |
1489 | One of its primary usecases is to prevent \e {Undefined Behavior} (UB) when |
1490 | comparing pointers. |
1491 | |
1492 | Consider the following simple class: |
1493 | |
1494 | \code |
1495 | template <typename T> |
1496 | struct PointerWrapperBad { |
1497 | int val; |
1498 | T *ptr; |
1499 | }; |
1500 | \endcode |
1501 | |
1502 | Lexicographical comparison of the two instances of the \c PointerWrapperBad |
1503 | type would result in UB, because it will call \c {operator<()} or |
1504 | \c {operator<=>()} on the \c {ptr} members. |
1505 | |
1506 | To fix it, use the new wrapper type: |
1507 | |
1508 | \code |
1509 | template <typename T> |
1510 | struct PointerWrapperGood { |
1511 | int val; |
1512 | Qt::totally_ordered_wrapper<T *> ptr; |
1513 | |
1514 | friend bool |
1515 | operator==(PointerWrapperGood lhs, PointerWrapperGood rhs) noexcept = default; |
1516 | friend auto |
1517 | operator<=>(PointerWrapperGood lhs, PointerWrapperGood rhs) noexecpt = default; |
1518 | }; |
1519 | \endcode |
1520 | |
1521 | The \c {operator<()} and (if available) \c {operator<=>()} operators for |
1522 | the \c {Qt::totally_ordered_wrapper} type use the |
1523 | \l {https://en.cppreference.com/w/cpp/utility/functional/less}{std::less} |
1524 | and \l {https://en.cppreference.com/w/cpp/utility/compare/compare_three_way} |
1525 | {std::compare_three_way} function objects respectively, providing |
1526 | \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} |
1527 | {strict total order over pointers} when doing the comparison. |
1528 | |
1529 | As a result, the relational operators for \c {PointerWrapperGood::ptr} |
1530 | member will be well-defined, and we can even \c {=default} the relational |
1531 | operators for the \c {PointerWrapperGood} class, like it's shown above. |
1532 | */ |
1533 | |
1534 | QT_END_NAMESPACE |
1535 | |