1 | // Copyright (C) 2023 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QCOMPARE_H |
5 | #error "Do not include qcomparehelpers.h directly. Use qcompare.h instead." |
6 | #endif |
7 | |
8 | #ifndef QCOMPAREHELPERS_H |
9 | #define QCOMPAREHELPERS_H |
10 | |
11 | #if 0 |
12 | #pragma qt_no_master_include |
13 | #pragma qt_sync_skip_header_check |
14 | #pragma qt_sync_stop_processing |
15 | #endif |
16 | |
17 | #include <QtCore/qoverload.h> |
18 | #include <QtCore/qttypetraits.h> |
19 | #include <QtCore/qtypeinfo.h> |
20 | #include <QtCore/qtypes.h> |
21 | |
22 | #ifdef __cpp_lib_three_way_comparison |
23 | #include <compare> |
24 | #endif |
25 | #include <QtCore/q20type_traits.h> |
26 | |
27 | #include <functional> // std::less, std::hash |
28 | |
29 | QT_BEGIN_NAMESPACE |
30 | |
31 | class QPartialOrdering; |
32 | |
33 | namespace QtOrderingPrivate { |
34 | #ifdef __cpp_lib_three_way_comparison |
35 | |
36 | template <typename QtOrdering> struct StdOrdering; |
37 | template <typename StdOrdering> struct QtOrdering; |
38 | |
39 | #define QT_STD_MAP(x) \ |
40 | template <> struct StdOrdering< Qt::x##_ordering> : q20::type_identity<std::x##_ordering> {};\ |
41 | template <> struct StdOrdering<std::x##_ordering> : q20::type_identity<std::x##_ordering> {};\ |
42 | template <> struct QtOrdering<std::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\ |
43 | template <> struct QtOrdering< Qt::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\ |
44 | /* end */ |
45 | QT_STD_MAP(partial) |
46 | QT_STD_MAP(weak) |
47 | QT_STD_MAP(strong) |
48 | #undef QT_STD_MAP |
49 | |
50 | template <> struct StdOrdering<QPartialOrdering> : q20::type_identity<std::partial_ordering> {}; |
51 | template <> struct QtOrdering<QPartialOrdering> : q20::type_identity< Qt::partial_ordering> {}; |
52 | |
53 | template <typename In> constexpr auto to_std(In in) noexcept |
54 | -> typename QtOrderingPrivate::StdOrdering<In>::type |
55 | { return in; } |
56 | |
57 | template <typename In> constexpr auto to_Qt(In in) noexcept |
58 | -> typename QtOrderingPrivate::QtOrdering<In>::type |
59 | { return in; } |
60 | |
61 | #endif // __cpp_lib_three_way_comparison |
62 | } // namespace QtOrderingPrivate |
63 | |
64 | /* |
65 | For all the macros these parameter names are used: |
66 | * LeftType - the type of the left operand of the comparison |
67 | * RightType - the type of the right operand of the comparison |
68 | * Constexpr - must be either constexpr or empty. Defines whether the |
69 | operator is constexpr or not |
70 | * Noexcept - a noexcept specifier. By default the relational operators are |
71 | expected to be noexcept. However, there are some cases when |
72 | this cannot be achieved (e.g. QDir). The public macros will |
73 | pass noexcept(true) or noexcept(false) in this parameter, |
74 | because conditional noexcept is known to cause some issues. |
75 | However, internally we might want to pass a predicate here |
76 | for some specific classes (e.g. QList, etc). |
77 | * Attributes - an optional list of attributes. For example, pass |
78 | \c QT_ASCII_CAST_WARN when defining comparisons between |
79 | C-style string and an encoding-aware string type. |
80 | |
81 | The macros require two helper functions. For operators to be constexpr, |
82 | these must be constexpr, too. Additionally, other attributes (like |
83 | Q_<Module>_EXPORT, Q_DECL_CONST_FUNCTION, etc) can be applied to them. |
84 | Aside from that, their declaration should match: |
85 | bool comparesEqual(LeftType, RightType) noexcept; |
86 | ReturnType compareThreeWay(LeftType, RightType) noexcept; |
87 | |
88 | The ReturnType can be one of Qt::{partial,weak,strong}_ordering. The actual |
89 | type depends on the macro being used. |
90 | It makes sense to define the helper functions as hidden friends of the |
91 | class, so that they could be found via ADL, and don't participate in |
92 | unintended implicit conversions. |
93 | */ |
94 | |
95 | /* |
96 | Some systems (e.g. QNX and Integrity (GHS compiler)) have bugs in |
97 | handling conditional noexcept in lambdas. |
98 | This macro is needed to overcome such bugs and provide a noexcept check only |
99 | on platforms that behave normally. |
100 | It does nothing on the systems that have problems. |
101 | */ |
102 | #if !defined(Q_OS_QNX) && !defined(Q_CC_GHS) |
103 | # define QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, Func) \ |
104 | constexpr auto f = []() Noexcept {}; \ |
105 | static_assert(!noexcept(f()) || noexcept(Func(lhs, rhs)), \ |
106 | "Use *_NON_NOEXCEPT version of the macro, " \ |
107 | "or make the helper function noexcept") |
108 | #else |
109 | # define QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, Func) /* no check */ |
110 | #endif |
111 | |
112 | |
113 | // Seems that qdoc uses C++20 even when Qt is compiled in C++17 mode. |
114 | // Or at least it defines __cpp_lib_three_way_comparison. |
115 | // Let qdoc see only the C++17 operators for now, because that's what our docs |
116 | // currently describe. |
117 | #if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC) |
118 | // C++20 - provide operator==() for equality, and operator<=>() for ordering |
119 | |
120 | #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, \ |
121 | Noexcept, Attributes) \ |
122 | Attributes \ |
123 | friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) Noexcept \ |
124 | { \ |
125 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, comparesEqual); \ |
126 | return comparesEqual(lhs, rhs); \ |
127 | } |
128 | |
129 | #define QT_DECLARE_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
130 | Attributes \ |
131 | friend Constexpr std::strong_ordering \ |
132 | operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \ |
133 | { \ |
134 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \ |
135 | return compareThreeWay(lhs, rhs); \ |
136 | } |
137 | |
138 | #define QT_DECLARE_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
139 | Attributes \ |
140 | friend Constexpr std::weak_ordering \ |
141 | operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \ |
142 | { \ |
143 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \ |
144 | return compareThreeWay(lhs, rhs); \ |
145 | } |
146 | |
147 | #define QT_DECLARE_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
148 | Attributes \ |
149 | friend Constexpr std::partial_ordering \ |
150 | operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \ |
151 | { \ |
152 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \ |
153 | return compareThreeWay(lhs, rhs); \ |
154 | } |
155 | |
156 | #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingType, LeftType, RightType, Constexpr, \ |
157 | Noexcept, Attributes) \ |
158 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
159 | QT_DECLARE_3WAY_HELPER_ ## OrderingType (LeftType, RightType, Constexpr, Noexcept, Attributes) |
160 | |
161 | #ifdef Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY |
162 | |
163 | // define reversed versions of the operators manually, because buggy MSVC versions do not do it |
164 | #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \ |
165 | Noexcept, Attributes) \ |
166 | Attributes \ |
167 | friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) Noexcept \ |
168 | { return comparesEqual(rhs, lhs); } |
169 | |
170 | #define QT_DECLARE_REVERSED_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr, \ |
171 | Noexcept, Attributes) \ |
172 | Attributes \ |
173 | friend Constexpr std::strong_ordering \ |
174 | operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \ |
175 | { \ |
176 | const auto r = compareThreeWay(rhs, lhs); \ |
177 | return QtOrderingPrivate::reversed(r); \ |
178 | } |
179 | |
180 | #define QT_DECLARE_REVERSED_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr, \ |
181 | Noexcept, Attributes) \ |
182 | Attributes \ |
183 | friend Constexpr std::weak_ordering \ |
184 | operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \ |
185 | { \ |
186 | const auto r = compareThreeWay(rhs, lhs); \ |
187 | return QtOrderingPrivate::reversed(r); \ |
188 | } |
189 | |
190 | #define QT_DECLARE_REVERSED_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr, \ |
191 | Noexcept, Attributes) \ |
192 | Attributes \ |
193 | friend Constexpr std::partial_ordering \ |
194 | operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \ |
195 | { \ |
196 | const auto r = compareThreeWay(rhs, lhs); \ |
197 | return QtOrderingPrivate::reversed(r); \ |
198 | } |
199 | |
200 | #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \ |
201 | Constexpr, Noexcept, Attributes) \ |
202 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \ |
203 | Noexcept, Attributes) \ |
204 | QT_DECLARE_REVERSED_3WAY_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, \ |
205 | Noexcept, Attributes) |
206 | |
207 | #else |
208 | |
209 | // dummy macros for C++17 compatibility, reversed operators are generated by the compiler |
210 | #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \ |
211 | Noexcept, Attributes) |
212 | #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \ |
213 | Constexpr, Noexcept, Attributes) |
214 | |
215 | #endif // Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY |
216 | |
217 | #else |
218 | // C++17 - provide operator==() and operator!=() for equality, |
219 | // and all 4 comparison operators for ordering |
220 | |
221 | #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, \ |
222 | Noexcept, Attributes) \ |
223 | Attributes \ |
224 | friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) Noexcept \ |
225 | { \ |
226 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, comparesEqual); \ |
227 | return comparesEqual(lhs, rhs); \ |
228 | } \ |
229 | Attributes \ |
230 | friend Constexpr bool operator!=(LeftType const &lhs, RightType const &rhs) Noexcept \ |
231 | { return !comparesEqual(lhs, rhs); } |
232 | |
233 | // Helpers for reversed comparison, using the existing comparesEqual() function. |
234 | #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \ |
235 | Noexcept, Attributes) \ |
236 | Attributes \ |
237 | friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) Noexcept \ |
238 | { return comparesEqual(rhs, lhs); } \ |
239 | Attributes \ |
240 | friend Constexpr bool operator!=(RightType const &lhs, LeftType const &rhs) Noexcept \ |
241 | { return !comparesEqual(rhs, lhs); } |
242 | |
243 | #define QT_DECLARE_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \ |
244 | Noexcept, Attributes) \ |
245 | Attributes \ |
246 | friend Constexpr bool operator<(LeftType const &lhs, RightType const &rhs) Noexcept \ |
247 | { \ |
248 | QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \ |
249 | return is_lt(compareThreeWay(lhs, rhs)); \ |
250 | } \ |
251 | Attributes \ |
252 | friend Constexpr bool operator>(LeftType const &lhs, RightType const &rhs) Noexcept \ |
253 | { return is_gt(compareThreeWay(lhs, rhs)); } \ |
254 | Attributes \ |
255 | friend Constexpr bool operator<=(LeftType const &lhs, RightType const &rhs) Noexcept \ |
256 | { return is_lteq(compareThreeWay(lhs, rhs)); } \ |
257 | Attributes \ |
258 | friend Constexpr bool operator>=(LeftType const &lhs, RightType const &rhs) Noexcept \ |
259 | { return is_gteq(compareThreeWay(lhs, rhs)); } |
260 | |
261 | #define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
262 | QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr, \ |
263 | Noexcept, Attributes) |
264 | |
265 | #define QT_DECLARE_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
266 | QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, Constexpr, \ |
267 | Noexcept, Attributes) |
268 | |
269 | #define QT_DECLARE_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
270 | QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, Constexpr, \ |
271 | Noexcept, Attributes) |
272 | |
273 | #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingString, LeftType, RightType, Constexpr, \ |
274 | Noexcept, Attributes) \ |
275 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Noexcept, Attributes) \ |
276 | QT_DECLARE_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, Noexcept, \ |
277 | Attributes) |
278 | |
279 | // Helpers for reversed ordering, using the existing compareThreeWay() function. |
280 | #define QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \ |
281 | Noexcept, Attributes) \ |
282 | Attributes \ |
283 | friend Constexpr bool operator<(RightType const &lhs, LeftType const &rhs) Noexcept \ |
284 | { return is_gt(compareThreeWay(rhs, lhs)); } \ |
285 | Attributes \ |
286 | friend Constexpr bool operator>(RightType const &lhs, LeftType const &rhs) Noexcept \ |
287 | { return is_lt(compareThreeWay(rhs, lhs)); } \ |
288 | Attributes \ |
289 | friend Constexpr bool operator<=(RightType const &lhs, LeftType const &rhs) Noexcept \ |
290 | { return is_gteq(compareThreeWay(rhs, lhs)); } \ |
291 | Attributes \ |
292 | friend Constexpr bool operator>=(RightType const &lhs, LeftType const &rhs) Noexcept \ |
293 | { return is_lteq(compareThreeWay(rhs, lhs)); } |
294 | |
295 | #define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, \ |
296 | Attributes) \ |
297 | QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, \ |
298 | Constexpr, Noexcept, Attributes) |
299 | |
300 | #define QT_DECLARE_REVERSED_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, \ |
301 | Attributes) \ |
302 | QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, \ |
303 | Constexpr, Noexcept, Attributes) |
304 | |
305 | #define QT_DECLARE_REVERSED_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, \ |
306 | Attributes) \ |
307 | QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, \ |
308 | Constexpr, Noexcept, Attributes) |
309 | |
310 | #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \ |
311 | Constexpr, Noexcept, Attributes) \ |
312 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Noexcept, \ |
313 | Attributes) \ |
314 | QT_DECLARE_REVERSED_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, \ |
315 | Noexcept, Attributes) |
316 | |
317 | #endif // __cpp_lib_three_way_comparison |
318 | |
319 | /* Public API starts here */ |
320 | |
321 | // Equality operators |
322 | #define QT_DECLARE_EQUALITY_COMPARABLE_1(Type) \ |
323 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */, noexcept(true), \ |
324 | /* no attributes */) |
325 | |
326 | #define QT_DECLARE_EQUALITY_COMPARABLE_2(LeftType, RightType) \ |
327 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \ |
328 | noexcept(true), /* no attributes */) \ |
329 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \ |
330 | noexcept(true), /* no attributes */) |
331 | |
332 | #define QT_DECLARE_EQUALITY_COMPARABLE_3(LeftType, RightType, Attributes) \ |
333 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \ |
334 | noexcept(true), Attributes) \ |
335 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \ |
336 | noexcept(true), Attributes) |
337 | |
338 | #define Q_DECLARE_EQUALITY_COMPARABLE(...) \ |
339 | QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE, __VA_ARGS__) |
340 | |
341 | #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_1(Type) \ |
342 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, constexpr, noexcept(true), \ |
343 | /* no attributes */) |
344 | |
345 | #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_2(LeftType, RightType) \ |
346 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, noexcept(true), \ |
347 | /* no attributes */) \ |
348 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, \ |
349 | noexcept(true), /* no attributes */) |
350 | |
351 | #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(LeftType, RightType, Attributes) \ |
352 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, noexcept(true), \ |
353 | Attributes) \ |
354 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, noexcept(true), \ |
355 | Attributes) |
356 | |
357 | #define Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(...) \ |
358 | QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE, __VA_ARGS__) |
359 | |
360 | #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_1(Type) \ |
361 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */, noexcept(false), \ |
362 | /* no attributes */) |
363 | |
364 | #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_2(LeftType, RightType) \ |
365 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \ |
366 | noexcept(false), /* no attributes */) \ |
367 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \ |
368 | noexcept(false), /* no attributes */) |
369 | |
370 | #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(LeftType, RightType, Attributes) \ |
371 | QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \ |
372 | noexcept(false), Attributes) \ |
373 | QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \ |
374 | noexcept(false), Attributes) |
375 | |
376 | #define Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(...) \ |
377 | QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT, __VA_ARGS__) |
378 | |
379 | // Partial ordering operators |
380 | #define QT_DECLARE_PARTIALLY_ORDERED_1(Type) \ |
381 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */, \ |
382 | noexcept(true), /* no attributes */) |
383 | |
384 | #define QT_DECLARE_PARTIALLY_ORDERED_2(LeftType, RightType) \ |
385 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \ |
386 | noexcept(true), /* no attributes */) \ |
387 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \ |
388 | /* non-constexpr */, noexcept(true), \ |
389 | /* no attributes */) |
390 | |
391 | #define QT_DECLARE_PARTIALLY_ORDERED_3(LeftType, RightType, Attributes) \ |
392 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \ |
393 | noexcept(true), Attributes) \ |
394 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \ |
395 | /* non-constexpr */, noexcept(true), Attributes) |
396 | |
397 | #define Q_DECLARE_PARTIALLY_ORDERED(...) \ |
398 | QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED, __VA_ARGS__) |
399 | |
400 | #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_1(Type) \ |
401 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, constexpr, noexcept(true), \ |
402 | /* no attributes */) |
403 | |
404 | #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \ |
405 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, \ |
406 | noexcept(true), /* no attributes */) \ |
407 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \ |
408 | noexcept(true), /* no attributes */) |
409 | |
410 | #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \ |
411 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, noexcept(true), \ |
412 | Attributes) \ |
413 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \ |
414 | noexcept(true), Attributes) |
415 | |
416 | #define Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(...) \ |
417 | QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE, __VA_ARGS__) |
418 | |
419 | #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_1(Type) \ |
420 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */, \ |
421 | noexcept(false), /* no attributes */) |
422 | |
423 | #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \ |
424 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \ |
425 | noexcept(false), /* no attributes */) \ |
426 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \ |
427 | /* non-constexpr */, noexcept(false), \ |
428 | /* no attributes */) |
429 | |
430 | #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, Attributes) \ |
431 | QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \ |
432 | noexcept(false), Attributes) \ |
433 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \ |
434 | /* non-constexpr */, noexcept(false), Attributes) |
435 | |
436 | #define Q_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT(...) \ |
437 | QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__) |
438 | |
439 | // Weak ordering operators |
440 | #define QT_DECLARE_WEAKLY_ORDERED_1(Type) \ |
441 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */, noexcept(true), \ |
442 | /* no attributes */) |
443 | |
444 | #define QT_DECLARE_WEAKLY_ORDERED_2(LeftType, RightType) \ |
445 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
446 | noexcept(true), /* no attributes */) \ |
447 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
448 | noexcept(true), /* no attributes */) |
449 | |
450 | #define QT_DECLARE_WEAKLY_ORDERED_3(LeftType, RightType, Attributes) \ |
451 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
452 | noexcept(true), Attributes) \ |
453 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
454 | noexcept(true), Attributes) |
455 | |
456 | #define Q_DECLARE_WEAKLY_ORDERED(...) \ |
457 | QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED, __VA_ARGS__) |
458 | |
459 | #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_1(Type) \ |
460 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, constexpr, noexcept(true), \ |
461 | /* no attributes */) |
462 | |
463 | #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \ |
464 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, \ |
465 | noexcept(true), /* no attributes */) \ |
466 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \ |
467 | noexcept(true), /* no attributes */) |
468 | |
469 | #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \ |
470 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, noexcept(true), \ |
471 | Attributes) \ |
472 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \ |
473 | noexcept(true), Attributes) |
474 | |
475 | #define Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(...) \ |
476 | QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE, __VA_ARGS__) |
477 | |
478 | #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_1(Type) \ |
479 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */, noexcept(false), \ |
480 | /* no attributes */) |
481 | |
482 | #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \ |
483 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
484 | noexcept(false), /* no attributes */) \ |
485 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
486 | noexcept(false), /* no attributes */) |
487 | |
488 | #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, Attributes) \ |
489 | QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
490 | noexcept(false), Attributes) \ |
491 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \ |
492 | noexcept(false), Attributes) |
493 | |
494 | #define Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(...) \ |
495 | QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__) |
496 | |
497 | // Strong ordering operators |
498 | #define QT_DECLARE_STRONGLY_ORDERED_1(Type) \ |
499 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */, \ |
500 | noexcept(true), /* no attributes */) |
501 | |
502 | #define QT_DECLARE_STRONGLY_ORDERED_2(LeftType, RightType) \ |
503 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \ |
504 | noexcept(true), /* no attributes */) \ |
505 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \ |
506 | /* non-constexpr */, noexcept(true), \ |
507 | /* no attributes */) |
508 | |
509 | #define QT_DECLARE_STRONGLY_ORDERED_3(LeftType, RightType, Attributes) \ |
510 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \ |
511 | noexcept(true), Attributes) \ |
512 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \ |
513 | /* non-constexpr */, noexcept(true), Attributes) |
514 | |
515 | #define Q_DECLARE_STRONGLY_ORDERED(...) \ |
516 | QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED, __VA_ARGS__) |
517 | |
518 | #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_1(Type) \ |
519 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, constexpr, noexcept(true), \ |
520 | /* no attributes */) |
521 | |
522 | #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \ |
523 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, \ |
524 | noexcept(true), /* no attributes */) \ |
525 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \ |
526 | noexcept(true), /* no attributes */) |
527 | |
528 | #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, Attributes) \ |
529 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, noexcept(true), \ |
530 | Attributes) \ |
531 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \ |
532 | noexcept(true), Attributes) |
533 | |
534 | #define Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(...) \ |
535 | QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE, __VA_ARGS__) |
536 | |
537 | #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_1(Type) \ |
538 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */, \ |
539 | noexcept(false), /* no attributes */) |
540 | |
541 | #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \ |
542 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \ |
543 | noexcept(false), /* no attributes */) \ |
544 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \ |
545 | /* non-constexpr */, noexcept(false), \ |
546 | /* no attributes */) |
547 | |
548 | #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, Attributes) \ |
549 | QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \ |
550 | noexcept(false), Attributes) \ |
551 | QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \ |
552 | /* non-constexpr */, noexcept(false), Attributes) |
553 | |
554 | #define Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(...) \ |
555 | QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__) |
556 | |
557 | namespace QtPrivate { |
558 | |
559 | template <typename T> |
560 | constexpr bool IsIntegralType_v = std::numeric_limits<std::remove_const_t<T>>::is_specialized |
561 | && std::numeric_limits<std::remove_const_t<T>>::is_integer; |
562 | |
563 | template <typename T> |
564 | constexpr bool IsFloatType_v = std::is_floating_point_v<T>; |
565 | |
566 | #if QFLOAT16_IS_NATIVE |
567 | template <> |
568 | inline constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true; |
569 | #endif |
570 | |
571 | } // namespace QtPrivate |
572 | |
573 | namespace QtOrderingPrivate { |
574 | |
575 | template <typename T, typename U> |
576 | constexpr Qt::strong_ordering |
577 | strongOrderingCompareDefaultImpl(T lhs, U rhs) noexcept |
578 | { |
579 | #ifdef __cpp_lib_three_way_comparison |
580 | return lhs <=> rhs; |
581 | #else |
582 | if (lhs == rhs) |
583 | return Qt::strong_ordering::equivalent; |
584 | else if (lhs < rhs) |
585 | return Qt::strong_ordering::less; |
586 | else |
587 | return Qt::strong_ordering::greater; |
588 | #endif // __cpp_lib_three_way_comparison |
589 | } |
590 | |
591 | } // namespace QtOrderingPrivate |
592 | |
593 | namespace Qt { |
594 | |
595 | template <typename T> |
596 | using if_integral = std::enable_if_t<QtPrivate::IsIntegralType_v<T>, bool>; |
597 | |
598 | template <typename T> |
599 | using if_floating_point = std::enable_if_t<QtPrivate::IsFloatType_v<T>, bool>; |
600 | |
601 | template <typename T, typename U> |
602 | using if_compatible_pointers = |
603 | std::enable_if_t<std::disjunction_v<std::is_same<T, U>, |
604 | std::is_base_of<T, U>, |
605 | std::is_base_of<U, T>>, |
606 | bool>; |
607 | |
608 | template <typename Enum> |
609 | using if_enum = std::enable_if_t<std::is_enum_v<Enum>, bool>; |
610 | |
611 | template <typename LeftInt, typename RightInt, |
612 | if_integral<LeftInt> = true, |
613 | if_integral<RightInt> = true> |
614 | constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept |
615 | { |
616 | static_assert(std::is_signed_v<LeftInt> == std::is_signed_v<RightInt>, |
617 | "Qt::compareThreeWay() does not allow mixed-sign comparison."); |
618 | |
619 | #ifdef __cpp_lib_three_way_comparison |
620 | return lhs <=> rhs; |
621 | #else |
622 | if (lhs == rhs) |
623 | return Qt::strong_ordering::equivalent; |
624 | else if (lhs < rhs) |
625 | return Qt::strong_ordering::less; |
626 | else |
627 | return Qt::strong_ordering::greater; |
628 | #endif // __cpp_lib_three_way_comparison |
629 | } |
630 | |
631 | template <typename LeftFloat, typename RightFloat, |
632 | if_floating_point<LeftFloat> = true, |
633 | if_floating_point<RightFloat> = true> |
634 | constexpr Qt::partial_ordering compareThreeWay(LeftFloat lhs, RightFloat rhs) noexcept |
635 | { |
636 | QT_WARNING_PUSH |
637 | QT_WARNING_DISABLE_FLOAT_COMPARE |
638 | #ifdef __cpp_lib_three_way_comparison |
639 | return lhs <=> rhs; |
640 | #else |
641 | if (lhs < rhs) |
642 | return Qt::partial_ordering::less; |
643 | else if (lhs > rhs) |
644 | return Qt::partial_ordering::greater; |
645 | else if (lhs == rhs) |
646 | return Qt::partial_ordering::equivalent; |
647 | else |
648 | return Qt::partial_ordering::unordered; |
649 | #endif // __cpp_lib_three_way_comparison |
650 | QT_WARNING_POP |
651 | } |
652 | |
653 | template <typename IntType, typename FloatType, |
654 | if_integral<IntType> = true, |
655 | if_floating_point<FloatType> = true> |
656 | constexpr Qt::partial_ordering compareThreeWay(IntType lhs, FloatType rhs) noexcept |
657 | { |
658 | return compareThreeWay(FloatType(lhs), rhs); |
659 | } |
660 | |
661 | template <typename FloatType, typename IntType, |
662 | if_floating_point<FloatType> = true, |
663 | if_integral<IntType> = true> |
664 | constexpr Qt::partial_ordering compareThreeWay(FloatType lhs, IntType rhs) noexcept |
665 | { |
666 | return compareThreeWay(lhs, FloatType(rhs)); |
667 | } |
668 | |
669 | #if QT_DEPRECATED_SINCE(6, 8) |
670 | |
671 | template <typename LeftType, typename RightType, |
672 | if_compatible_pointers<LeftType, RightType> = true> |
673 | QT_DEPRECATED_VERSION_X_6_8("Wrap the pointers into Qt::totally_ordered_wrapper and use the respective overload instead.") |
674 | constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightType *rhs) noexcept |
675 | { |
676 | #ifdef __cpp_lib_three_way_comparison |
677 | return std::compare_three_way{}(lhs, rhs); |
678 | #else |
679 | if (lhs == rhs) |
680 | return Qt::strong_ordering::equivalent; |
681 | else if (std::less<>{}(lhs, rhs)) |
682 | return Qt::strong_ordering::less; |
683 | else |
684 | return Qt::strong_ordering::greater; |
685 | #endif // __cpp_lib_three_way_comparison |
686 | } |
687 | |
688 | template <typename T> |
689 | QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.") |
690 | constexpr Qt::strong_ordering compareThreeWay(const T *lhs, std::nullptr_t rhs) noexcept |
691 | { |
692 | return compareThreeWay(lhs, static_cast<const T *>(rhs)); |
693 | } |
694 | |
695 | template <typename T> |
696 | QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.") |
697 | constexpr Qt::strong_ordering compareThreeWay(std::nullptr_t lhs, const T *rhs) noexcept |
698 | { |
699 | return compareThreeWay(static_cast<const T *>(lhs), rhs); |
700 | } |
701 | |
702 | #endif // QT_DEPRECATED_SINCE(6, 8) |
703 | |
704 | template <class Enum, if_enum<Enum> = true> |
705 | constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept |
706 | { |
707 | return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs)); |
708 | } |
709 | } // namespace Qt |
710 | |
711 | namespace QtOrderingPrivate { |
712 | |
713 | template <typename Head, typename...Tail, std::size_t...Is> |
714 | constexpr std::tuple<Tail...> qt_tuple_pop_front_impl(const std::tuple<Head, Tail...> &t, |
715 | std::index_sequence<Is...>) noexcept |
716 | { |
717 | return std::tuple<Tail...>(std::get<Is + 1>(t)...); |
718 | } |
719 | |
720 | template <typename Head, typename...Tail> |
721 | constexpr std::tuple<Tail...> qt_tuple_pop_front(const std::tuple<Head, Tail...> &t) noexcept |
722 | { |
723 | return qt_tuple_pop_front_impl(t, std::index_sequence_for<Tail...>{}); |
724 | } |
725 | |
726 | template <typename LhsHead, typename...LhsTail, typename RhsHead, typename...RhsTail> |
727 | constexpr auto compareThreeWayMulti(const std::tuple<LhsHead, LhsTail...> &lhs, // ie. not empty |
728 | const std::tuple<RhsHead, RhsTail...> &rhs) noexcept |
729 | { |
730 | static_assert(sizeof...(LhsTail) == sizeof...(RhsTail), |
731 | // expanded together below, but provide a nicer error message: |
732 | "The tuple arguments have to have the same size."); |
733 | |
734 | using Qt::compareThreeWay; |
735 | using R = std::common_type_t< |
736 | decltype(compareThreeWay(std::declval<LhsHead>(), std::declval<RhsHead>())), |
737 | decltype(compareThreeWay(std::declval<LhsTail>(), std::declval<RhsTail>()))... |
738 | >; |
739 | |
740 | const auto &l = std::get<0>(lhs); |
741 | const auto &r = std::get<0>(rhs); |
742 | static_assert(noexcept(compareThreeWay(l, r)), |
743 | "This function requires all relational operators to be noexcept."); |
744 | const auto res = compareThreeWay(l, r); |
745 | if constexpr (sizeof...(LhsTail) > 0) { |
746 | if (is_eq(res)) |
747 | return R{compareThreeWayMulti(qt_tuple_pop_front(lhs), qt_tuple_pop_front(rhs))}; |
748 | } |
749 | return R{res}; |
750 | } |
751 | |
752 | } //QtOrderingPrivate |
753 | |
754 | namespace Qt { |
755 | // A wrapper class that adapts the wrappee to use the strongly-ordered |
756 | // <functional> function objects for implementing the relational operators. |
757 | // Mostly useful to avoid UB on pointers (which it currently mandates P to be), |
758 | // because all the comparison helpers (incl. std::compare_three_way on |
759 | // std::tuple<T*>!) will use the language-level operators. |
760 | // |
761 | template <typename P> |
762 | class totally_ordered_wrapper |
763 | { |
764 | static_assert(std::is_pointer_v<P>); |
765 | using T = std::remove_pointer_t<P>; |
766 | |
767 | P ptr; |
768 | public: |
769 | totally_ordered_wrapper() noexcept = default; |
770 | Q_IMPLICIT constexpr totally_ordered_wrapper(std::nullptr_t) |
771 | // requires std::is_pointer_v<P> |
772 | : totally_ordered_wrapper(P{nullptr}) {} |
773 | explicit constexpr totally_ordered_wrapper(P p) noexcept : ptr(p) {} |
774 | |
775 | constexpr P get() const noexcept { return ptr; } |
776 | constexpr void reset(P p) noexcept { ptr = p; } |
777 | constexpr P operator->() const noexcept { return get(); } |
778 | template <typename U = T, std::enable_if_t<!std::is_void_v<U>, bool> = true> |
779 | constexpr U &operator*() const noexcept { return *get(); } |
780 | |
781 | explicit constexpr operator bool() const noexcept { return get(); } |
782 | |
783 | private: |
784 | // TODO: Replace the constraints with std::common_type_t<P, U> when |
785 | // a bug in VxWorks is fixed! |
786 | template <typename T, typename U> |
787 | using if_compatible_types = |
788 | std::enable_if_t<std::conjunction_v<std::is_pointer<T>, |
789 | std::is_pointer<U>, |
790 | std::disjunction<std::is_convertible<T, U>, |
791 | std::is_convertible<U, T>>>, |
792 | bool>; |
793 | |
794 | #define MAKE_RELOP(Ret, op, Op) \ |
795 | template <typename U = P, if_compatible_types<P, U> = true> \ |
796 | friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const totally_ordered_wrapper<U> &rhs) noexcept \ |
797 | { return std:: Op {}(lhs.ptr, rhs.get()); } \ |
798 | template <typename U = P, if_compatible_types<P, U> = true> \ |
799 | friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const U &rhs) noexcept \ |
800 | { return std:: Op {}(lhs.ptr, rhs ); } \ |
801 | template <typename U = P, if_compatible_types<P, U> = true> \ |
802 | friend constexpr Ret operator op (const U &lhs, const totally_ordered_wrapper<P> &rhs) noexcept \ |
803 | { return std:: Op {}(lhs, rhs.ptr); } \ |
804 | friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, std::nullptr_t) noexcept \ |
805 | { return std:: Op {}(lhs.ptr, P(nullptr)); } \ |
806 | friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \ |
807 | { return std:: Op {}(P(nullptr), rhs.ptr); } \ |
808 | /* end */ |
809 | MAKE_RELOP(bool, ==, equal_to<>) |
810 | MAKE_RELOP(bool, !=, not_equal_to<>) |
811 | MAKE_RELOP(bool, < , less<>) |
812 | MAKE_RELOP(bool, <=, less_equal<>) |
813 | MAKE_RELOP(bool, > , greater<>) |
814 | MAKE_RELOP(bool, >=, greater_equal<>) |
815 | #ifdef __cpp_lib_three_way_comparison |
816 | MAKE_RELOP(auto, <=>, compare_three_way) |
817 | #endif |
818 | #undef MAKE_RELOP |
819 | friend void qt_ptr_swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept |
820 | { qt_ptr_swap(lhs.ptr, rhs.ptr); } |
821 | friend void swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept |
822 | { qt_ptr_swap(lhs, rhs); } |
823 | friend size_t qHash(totally_ordered_wrapper key, size_t seed = 0) noexcept |
824 | { return qHash(key.ptr, seed); } |
825 | }; |
826 | |
827 | template <typename T, typename U, if_compatible_pointers<T, U> = true> |
828 | constexpr Qt::strong_ordering |
829 | compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<U*> rhs) noexcept |
830 | { |
831 | return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); |
832 | } |
833 | |
834 | template <typename T, typename U, if_compatible_pointers<T, U> = true> |
835 | constexpr Qt::strong_ordering |
836 | compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, U *rhs) noexcept |
837 | { |
838 | return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); |
839 | } |
840 | |
841 | template <typename T, typename U, if_compatible_pointers<T, U> = true> |
842 | constexpr Qt::strong_ordering |
843 | compareThreeWay(U *lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept |
844 | { |
845 | return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); |
846 | } |
847 | |
848 | template <typename T> |
849 | constexpr Qt::strong_ordering |
850 | compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) noexcept |
851 | { |
852 | return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); |
853 | } |
854 | |
855 | template <typename T> |
856 | constexpr Qt::strong_ordering |
857 | compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept |
858 | { |
859 | return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); |
860 | } |
861 | |
862 | } //Qt |
863 | |
864 | template <typename P> |
865 | class QTypeInfo<Qt::totally_ordered_wrapper<P>> : public QTypeInfo<P> {}; |
866 | |
867 | QT_END_NAMESPACE |
868 | |
869 | namespace std { |
870 | template <typename P> |
871 | struct hash<QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>> |
872 | { |
873 | using argument_type = QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>; |
874 | using result_type = size_t; |
875 | constexpr result_type operator()(argument_type w) const noexcept |
876 | { return std::hash<P>{}(w.get()); } |
877 | }; |
878 | } |
879 | |
880 | #endif // QCOMPAREHELPERS_H |
881 |
Definitions
- IsIntegralType_v
- IsFloatType_v
- strongOrderingCompareDefaultImpl
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- qt_tuple_pop_front_impl
- qt_tuple_pop_front
- compareThreeWayMulti
- totally_ordered_wrapper
- totally_ordered_wrapper
- totally_ordered_wrapper
- totally_ordered_wrapper
- get
- reset
- operator->
- operator*
- operator bool
- qt_ptr_swap
- swap
- qHash
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- compareThreeWay
- QTypeInfo
- hash
Learn to use CMake with our Intro Training
Find out more