Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:12

0001 // Copyright (C) 2023 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QCOMPARE_H
0005 #error "Do not include qcomparehelpers.h directly. Use qcompare.h instead."
0006 #endif
0007 
0008 #ifndef QCOMPAREHELPERS_H
0009 #define QCOMPAREHELPERS_H
0010 
0011 #if 0
0012 #pragma qt_no_master_include
0013 #pragma qt_sync_skip_header_check
0014 #pragma qt_sync_stop_processing
0015 #endif
0016 
0017 #include <QtCore/qflags.h>
0018 #include <QtCore/qoverload.h>
0019 #include <QtCore/qttypetraits.h>
0020 #include <QtCore/qtypeinfo.h>
0021 #include <QtCore/qtypes.h>
0022 
0023 #ifdef __cpp_lib_three_way_comparison
0024 #include <compare>
0025 #endif
0026 #include <QtCore/q20type_traits.h>
0027 
0028 #include <functional> // std::less, std::hash
0029 
0030 QT_BEGIN_NAMESPACE
0031 
0032 class QPartialOrdering;
0033 
0034 namespace QtOrderingPrivate {
0035 template <typename T> struct is_std_ordering_type : std::false_type {};
0036 template <typename T> struct is_qt_ordering_type : std::false_type {};
0037 
0038 template <typename T> constexpr bool is_std_ordering_type_v = is_std_ordering_type<T>::value;
0039 template <typename T> constexpr bool is_qt_ordering_type_v = is_qt_ordering_type<T>::value;
0040 
0041 enum class QtOrderingType {
0042     QtOrder =  0x00,
0043     StdOrder = 0x01,
0044     Partial = 0x00,
0045     Weak = 0x20,
0046     Strong = 0x40,
0047     StrengthMask = Weak|Strong,
0048 };
0049 Q_DECLARE_FLAGS(QtOrderingTypeFlag, QtOrderingType)
0050 Q_DECLARE_OPERATORS_FOR_FLAGS(QtOrderingPrivate::QtOrderingTypeFlag)
0051 
0052 template <typename QtOrdering> struct StdOrdering;
0053 template <typename StdOrdering> struct QtOrdering;
0054 
0055 #ifdef __cpp_lib_three_way_comparison
0056 #define QT_STD_MAP(x) \
0057     template <> struct StdOrdering< Qt::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
0058     template <> struct StdOrdering<std::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
0059     template <> struct  QtOrdering<std::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
0060     template <> struct  QtOrdering< Qt::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
0061     template <> struct is_std_ordering_type<std::x##_ordering> : std::true_type {};\
0062     template <> struct is_qt_ordering_type< Qt::x##_ordering> : std::true_type {};\
0063     /* end */
0064 QT_STD_MAP(partial)
0065 QT_STD_MAP(weak)
0066 QT_STD_MAP(strong)
0067 #undef QT_STD_MAP
0068 
0069 template <> struct StdOrdering<QPartialOrdering> : q20::type_identity<std::partial_ordering> {};
0070 template <> struct  QtOrdering<QPartialOrdering> : q20::type_identity< Qt::partial_ordering> {};
0071 #else
0072 template <> struct is_qt_ordering_type< Qt::partial_ordering> : std::true_type {};
0073 template <> struct is_qt_ordering_type< Qt::weak_ordering> : std::true_type {};
0074 template <> struct is_qt_ordering_type< Qt::strong_ordering> : std::true_type {};
0075 #endif // __cpp_lib_three_way_comparison
0076 
0077 template <typename In> constexpr auto to_std(In in) noexcept
0078     -> typename QtOrderingPrivate::StdOrdering<In>::type
0079 { return in; }
0080 
0081 template <typename In> constexpr auto to_Qt(In in) noexcept
0082     -> typename QtOrderingPrivate::QtOrdering<In>::type
0083 { return in; }
0084 
0085 template <typename T>
0086 constexpr bool is_ordering_type_v
0087         = std::disjunction_v<is_qt_ordering_type<T>, is_std_ordering_type<T>>;
0088 
0089 template <typename T>
0090 constexpr std::enable_if_t<is_qt_ordering_type_v<T>, QtOrderingTypeFlag>
0091 orderingFlagsFor(T t) noexcept
0092 {
0093     QtOrderingTypeFlag flags = QtOrderingType::QtOrder;
0094     Qt::partial_ordering convertedOrder(t);
0095     if constexpr (std::is_same_v<T, Qt::strong_ordering>)
0096         flags = flags | QtOrderingType::Strong;
0097     else if constexpr (std::is_same_v<T, Qt::partial_ordering>)
0098         flags = flags | QtOrderingType::Partial;
0099     else if constexpr (std::is_same_v<T, Qt::weak_ordering>)
0100         flags = flags | QtOrderingType::Weak;
0101     return flags;
0102 }
0103 
0104 template <typename T>
0105 constexpr std::enable_if_t<is_std_ordering_type_v<T>, QtOrderingTypeFlag>
0106 orderingFlagsFor(T t) noexcept
0107 {
0108     QtOrderingPrivate::QtOrderingTypeFlag flags = QtOrderingPrivate::QtOrderingType::StdOrder;
0109     return QtOrderingTypeFlag(flags
0110                               | QtOrderingPrivate::orderingFlagsFor(QtOrderingPrivate::to_Qt(t)));
0111 }
0112 } // namespace QtOrderingPrivate
0113 
0114 /*
0115     For all the macros these parameter names are used:
0116     * LeftType - the type of the left operand of the comparison
0117     * RightType - the type of the right operand of the comparison
0118     * Constexpr - must be either constexpr or empty. Defines whether the
0119                   operator is constexpr or not
0120     * Noexcept - a noexcept specifier. By default the relational operators are
0121                  expected to be noexcept. However, there are some cases when
0122                  this cannot be achieved (e.g. QDir). The public macros will
0123                  pass noexcept(true) or noexcept(false) in this parameter,
0124                  because conditional noexcept is known to cause some issues.
0125                  However, internally we might want to pass a predicate here
0126                  for some specific classes (e.g. QList, etc).
0127     * Attributes... - an optional list of attributes. For example, pass
0128                       \c QT_ASCII_CAST_WARN when defining comparisons between
0129                       C-style string and an encoding-aware string type.
0130                       This is a variable argument, and can now include up to 7
0131                       comma-separated parameters.
0132 
0133     The macros require two helper functions. For operators to be constexpr,
0134     these must be constexpr, too. Additionally, other attributes (like
0135     Q_<Module>_EXPORT, Q_DECL_CONST_FUNCTION, etc) can be applied to them.
0136     Aside from that, their declaration should match:
0137         bool comparesEqual(LeftType, RightType) noexcept;
0138         ReturnType compareThreeWay(LeftType, RightType) noexcept;
0139 
0140     The ReturnType can be one of Qt::{partial,weak,strong}_ordering. The actual
0141     type depends on the macro being used.
0142     It makes sense to define the helper functions as hidden friends of the
0143     class, so that they could be found via ADL, and don't participate in
0144     unintended implicit conversions.
0145 */
0146 
0147 /*
0148     Some systems (e.g. QNX and Integrity (GHS compiler)) have bugs in
0149     handling conditional noexcept in lambdas.
0150     This macro is needed to overcome such bugs and provide a noexcept check only
0151     on platforms that behave normally.
0152     It does nothing on the systems that have problems.
0153 
0154     This hack is explicitly disabled for C++20 because we want the compilers
0155     to fix the known issues before switching.
0156 */
0157 #if defined(__cpp_lib_three_way_comparison) || !(defined(Q_OS_QNX) || defined(Q_CC_GHS))
0158 # define QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, Func) \
0159     constexpr auto f = []() Noexcept {}; \
0160     static_assert(!noexcept(f()) || noexcept(Func(lhs, rhs)), \
0161                   "Use *_NON_NOEXCEPT version of the macro, " \
0162                   "or make the helper function noexcept")
0163 #else
0164 # define QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, Func) /* no check */
0165 #endif
0166 
0167 
0168 // Seems that qdoc uses C++20 even when Qt is compiled in C++17 mode.
0169 // Or at least it defines __cpp_lib_three_way_comparison.
0170 // Let qdoc see only the C++17 operators for now, because that's what our docs
0171 // currently describe.
0172 #if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC)
0173 // C++20 - provide operator==() for equality, and operator<=>() for ordering
0174 
0175 #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, \
0176                                              Noexcept, ...) \
0177     __VA_ARGS__ \
0178     friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) Noexcept \
0179     { \
0180         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, comparesEqual); \
0181         return comparesEqual(lhs, rhs); \
0182     }
0183 
0184 #define QT_DECLARE_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, ...) \
0185     __VA_ARGS__ \
0186     friend Constexpr std::strong_ordering \
0187     operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \
0188     { \
0189         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \
0190         return compareThreeWay(lhs, rhs); \
0191     }
0192 
0193 #define QT_DECLARE_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, ...) \
0194     __VA_ARGS__ \
0195     friend Constexpr std::weak_ordering \
0196     operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \
0197     { \
0198         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \
0199         return compareThreeWay(lhs, rhs); \
0200     }
0201 
0202 #define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, ...) \
0203     __VA_ARGS__ \
0204     friend Constexpr std::partial_ordering \
0205     operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \
0206     { \
0207         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \
0208         return compareThreeWay(lhs, rhs); \
0209     }
0210 
0211 #define QT_DECLARE_ORDERING_HELPER_AUTO(LeftType, RightType, Constexpr, Noexcept, ...) \
0212     __VA_ARGS__ \
0213     friend Constexpr auto \
0214     operator<=>(LeftType const &lhs, RightType const &rhs) Noexcept \
0215     { \
0216         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay);\
0217         return QtOrderingPrivate::to_std(compareThreeWay(lhs, rhs)); \
0218     }
0219 
0220 #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingType, LeftType, RightType, Constexpr, \
0221                                              Noexcept, ...) \
0222     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Noexcept, __VA_ARGS__) \
0223     QT_DECLARE_ORDERING_HELPER_ ## OrderingType (LeftType, RightType, Constexpr, Noexcept, \
0224                                                  __VA_ARGS__)
0225 
0226 #ifdef Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
0227 
0228 // define reversed versions of the operators manually, because buggy MSVC versions do not do it
0229 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \
0230                                                       Noexcept, ...) \
0231     __VA_ARGS__ \
0232     friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) Noexcept \
0233     { return comparesEqual(rhs, lhs); }
0234 
0235 #define QT_DECLARE_REVERSED_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, \
0236                                                    Noexcept, ...) \
0237     __VA_ARGS__ \
0238     friend Constexpr std::strong_ordering \
0239     operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \
0240     { \
0241         const auto r = compareThreeWay(rhs, lhs); \
0242         return QtOrderingPrivate::reversed(r); \
0243     }
0244 
0245 #define QT_DECLARE_REVERSED_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, \
0246                                                  Noexcept, ...) \
0247     __VA_ARGS__ \
0248     friend Constexpr std::weak_ordering \
0249     operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \
0250     { \
0251         const auto r = compareThreeWay(rhs, lhs); \
0252         return QtOrderingPrivate::reversed(r); \
0253     }
0254 
0255 #define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, \
0256                                                     Noexcept, ...) \
0257     __VA_ARGS__ \
0258     friend Constexpr std::partial_ordering \
0259     operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \
0260     { \
0261         const auto r = compareThreeWay(rhs, lhs); \
0262         return QtOrderingPrivate::reversed(r); \
0263     }
0264 
0265 #define QT_DECLARE_REVERSED_ORDERING_HELPER_AUTO(LeftType, RightType, Constexpr, Noexcept, ...) \
0266     __VA_ARGS__ \
0267     friend Constexpr auto \
0268     operator<=>(RightType const &lhs, LeftType const &rhs) Noexcept \
0269     { \
0270         const auto r = compareThreeWay(rhs, lhs); \
0271         return QtOrderingPrivate::to_std(QtOrderingPrivate::reversed(r)); \
0272     }
0273 
0274 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
0275                                                       Constexpr, Noexcept, ...) \
0276     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \
0277                                                   Noexcept, __VA_ARGS__) \
0278     QT_DECLARE_REVERSED_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, \
0279                                                             Noexcept, __VA_ARGS__)
0280 
0281 #else
0282 
0283 // dummy macros for C++17 compatibility, reversed operators are generated by the compiler
0284 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \
0285                                                       Noexcept, ...)
0286 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
0287                                                       Constexpr, Noexcept, ...)
0288 
0289 #endif // Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
0290 
0291 #else
0292 // C++17 - provide operator==() and operator!=() for equality,
0293 // and all 4 comparison operators for ordering
0294 
0295 #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, \
0296                                              Noexcept, ...) \
0297     __VA_ARGS__ \
0298     friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) Noexcept \
0299     { \
0300         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, comparesEqual); \
0301         return comparesEqual(lhs, rhs); \
0302     } \
0303     __VA_ARGS__ \
0304     friend Constexpr bool operator!=(LeftType const &lhs, RightType const &rhs) Noexcept \
0305     { return !comparesEqual(lhs, rhs); }
0306 
0307 // Helpers for reversed comparison, using the existing comparesEqual() function.
0308 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, \
0309                                                       Noexcept, ...) \
0310     __VA_ARGS__ \
0311     friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) Noexcept \
0312     { return comparesEqual(rhs, lhs); } \
0313     __VA_ARGS__ \
0314     friend Constexpr bool operator!=(RightType const &lhs, LeftType const &rhs) Noexcept \
0315     { return !comparesEqual(rhs, lhs); }
0316 
0317 #define QT_DECLARE_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \
0318                                             Noexcept, ...) \
0319     __VA_ARGS__ \
0320     friend Constexpr bool operator<(LeftType const &lhs, RightType const &rhs) Noexcept \
0321     { \
0322         QT_COMPARISON_NOEXCEPT_CHECK(Noexcept, compareThreeWay); \
0323         return is_lt(compareThreeWay(lhs, rhs)); \
0324     } \
0325     __VA_ARGS__ \
0326     friend Constexpr bool operator>(LeftType const &lhs, RightType const &rhs) Noexcept \
0327     { return is_gt(compareThreeWay(lhs, rhs)); } \
0328     __VA_ARGS__ \
0329     friend Constexpr bool operator<=(LeftType const &lhs, RightType const &rhs) Noexcept \
0330     { return is_lteq(compareThreeWay(lhs, rhs)); } \
0331     __VA_ARGS__ \
0332     friend Constexpr bool operator>=(LeftType const &lhs, RightType const &rhs) Noexcept \
0333     { return is_gteq(compareThreeWay(lhs, rhs)); }
0334 
0335 #define QT_DECLARE_ORDERING_HELPER_AUTO(LeftType, RightType, Constexpr, Noexcept, ...) \
0336     QT_DECLARE_ORDERING_HELPER_TEMPLATE(auto, LeftType, RightType, Constexpr, Noexcept, \
0337                                         __VA_ARGS__)
0338 
0339 #define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, ...) \
0340     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr, \
0341                                         Noexcept, __VA_ARGS__)
0342 
0343 #define QT_DECLARE_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, ...) \
0344     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, Constexpr, \
0345                                         Noexcept, __VA_ARGS__)
0346 
0347 #define QT_DECLARE_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, ...) \
0348     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, Constexpr, \
0349                                         Noexcept, __VA_ARGS__)
0350 
0351 #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingString, LeftType, RightType, Constexpr, \
0352                                              Noexcept, ...) \
0353     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr, Noexcept, __VA_ARGS__) \
0354     QT_DECLARE_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, Noexcept, \
0355                                                    __VA_ARGS__)
0356 
0357 // Helpers for reversed ordering, using the existing compareThreeWay() function.
0358 #define QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr, \
0359                                                      Noexcept, ...) \
0360     __VA_ARGS__ \
0361     friend Constexpr bool operator<(RightType const &lhs, LeftType const &rhs) Noexcept \
0362     { return is_gt(compareThreeWay(rhs, lhs)); } \
0363     __VA_ARGS__ \
0364     friend Constexpr bool operator>(RightType const &lhs, LeftType const &rhs) Noexcept \
0365     { return is_lt(compareThreeWay(rhs, lhs)); } \
0366     __VA_ARGS__ \
0367     friend Constexpr bool operator<=(RightType const &lhs, LeftType const &rhs) Noexcept \
0368     { return is_gteq(compareThreeWay(rhs, lhs)); } \
0369     __VA_ARGS__ \
0370     friend Constexpr bool operator>=(RightType const &lhs, LeftType const &rhs) Noexcept \
0371     { return is_lteq(compareThreeWay(rhs, lhs)); }
0372 
0373 #define QT_DECLARE_REVERSED_ORDERING_HELPER_AUTO(LeftType, RightType, Constexpr, Noexcept, ...) \
0374     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(auto, LeftType, RightType, Constexpr, Noexcept, \
0375                                                  __VA_ARGS__)
0376 
0377 #define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Noexcept, ...) \
0378     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, \
0379                                                  Constexpr, Noexcept, __VA_ARGS__)
0380 
0381 #define QT_DECLARE_REVERSED_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr, Noexcept, ...) \
0382     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, \
0383                                                  Constexpr, Noexcept, __VA_ARGS__)
0384 
0385 #define QT_DECLARE_REVERSED_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr, Noexcept, ...) \
0386     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, \
0387                                                  Constexpr, Noexcept, __VA_ARGS__)
0388 
0389 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
0390                                                       Constexpr, Noexcept, ...) \
0391     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr, Noexcept, \
0392                                                   __VA_ARGS__) \
0393     QT_DECLARE_REVERSED_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr, \
0394                                                             Noexcept, __VA_ARGS__)
0395 
0396 #endif // __cpp_lib_three_way_comparison
0397 
0398 /* Public API starts here */
0399 
0400 // Equality operators
0401 #define QT_DECLARE_EQUALITY_COMPARABLE_1(Type) \
0402     QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */, noexcept(true), \
0403                                          /* no attributes */)
0404 
0405 #define QT_DECLARE_EQUALITY_COMPARABLE_2(LeftType, RightType) \
0406     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \
0407                                          noexcept(true), /* no attributes */) \
0408     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
0409                                                   noexcept(true), /* no attributes */)
0410 
0411 #define QT_DECLARE_EQUALITY_COMPARABLE_3(LeftType, RightType, ...) \
0412     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \
0413                                          noexcept(true), __VA_ARGS__) \
0414     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
0415                                                   noexcept(true), __VA_ARGS__)
0416 
0417 #define QT_DECLARE_EQUALITY_COMPARABLE_4(...) \
0418     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0419 #define QT_DECLARE_EQUALITY_COMPARABLE_5(...) \
0420     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0421 #define QT_DECLARE_EQUALITY_COMPARABLE_6(...) \
0422     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0423 #define QT_DECLARE_EQUALITY_COMPARABLE_7(...) \
0424     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0425 #define QT_DECLARE_EQUALITY_COMPARABLE_8(...) \
0426     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0427 #define QT_DECLARE_EQUALITY_COMPARABLE_9(...) \
0428     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_3(__VA_ARGS__))
0429 
0430 #define Q_DECLARE_EQUALITY_COMPARABLE(...) \
0431     QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE, __VA_ARGS__)
0432 
0433 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_1(Type) \
0434     QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, constexpr, noexcept(true), \
0435                                          /* no attributes */)
0436 
0437 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_2(LeftType, RightType) \
0438     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, noexcept(true), \
0439                                          /* no attributes */) \
0440     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, \
0441                                                   noexcept(true), /* no attributes */)
0442 
0443 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(LeftType, RightType, ...) \
0444     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr, noexcept(true), \
0445                                          __VA_ARGS__) \
0446     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr, noexcept(true), \
0447                                                   __VA_ARGS__)
0448 
0449 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_4(...) \
0450     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0451 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_5(...) \
0452     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0453 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_6(...) \
0454     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0455 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_7(...) \
0456     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0457 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_8(...) \
0458     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0459 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_9(...) \
0460     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_3(__VA_ARGS__))
0461 
0462 #define Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(...) \
0463     QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE, __VA_ARGS__)
0464 
0465 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_1(Type) \
0466     QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */, noexcept(false), \
0467                                          /* no attributes */)
0468 
0469 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_2(LeftType, RightType) \
0470     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \
0471                                          noexcept(false), /* no attributes */) \
0472     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
0473                                                   noexcept(false), /* no attributes */)
0474 
0475 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(LeftType, RightType, ...) \
0476     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */, \
0477                                          noexcept(false), __VA_ARGS__) \
0478     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */, \
0479                                                   noexcept(false), __VA_ARGS__)
0480 
0481 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_4(...) \
0482     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0483 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_5(...) \
0484     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0485 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_6(...) \
0486     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0487 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_7(...) \
0488     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0489 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_8(...) \
0490     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0491 #define QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_9(...) \
0492     QT_VA_ARGS_EXPAND(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT_3(__VA_ARGS__))
0493 
0494 #define Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(...) \
0495     QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT, __VA_ARGS__)
0496 
0497 // Ordering operators that automatically deduce the strength:
0498 #define QT_DECLARE_ORDERED_1(Type) \
0499     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, Type, Type, /* non-constexpr */, noexcept(true), \
0500                                          /* no attributes */)
0501 
0502 #define QT_DECLARE_ORDERED_2(LeftType, RightType) \
0503     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0504                                          noexcept(true), /* no attributes */) \
0505     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0506                                                   noexcept(true), /* no attributes */)
0507 
0508 #define QT_DECLARE_ORDERED_3(LeftType, RightType, ...) \
0509     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0510                                          noexcept(true), __VA_ARGS__) \
0511     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0512                                                   noexcept(true), __VA_ARGS__)
0513 
0514 #define QT_DECLARE_ORDERED_4(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0515 #define QT_DECLARE_ORDERED_5(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0516 #define QT_DECLARE_ORDERED_6(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0517 #define QT_DECLARE_ORDERED_7(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0518 #define QT_DECLARE_ORDERED_8(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0519 #define QT_DECLARE_ORDERED_9(...) QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_3(__VA_ARGS__))
0520 
0521 #define Q_DECLARE_ORDERED(...) QT_OVERLOADED_MACRO(QT_DECLARE_ORDERED, __VA_ARGS__)
0522 
0523 #define QT_DECLARE_ORDERED_LITERAL_TYPE_1(Type) \
0524     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, Type, Type, constexpr, noexcept(true), \
0525                                          /* no attributes */)
0526 
0527 #define QT_DECLARE_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0528     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, constexpr, \
0529                                          noexcept(true), /* no attributes */) \
0530     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, constexpr, \
0531                                                   noexcept(true), /* no attributes */)
0532 
0533 #define QT_DECLARE_ORDERED_LITERAL_TYPE_3(LeftType, RightType, ...) \
0534     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, constexpr, \
0535                                          noexcept(true), __VA_ARGS__) \
0536     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, constexpr, \
0537                                                   noexcept(true), __VA_ARGS__)
0538 
0539 #define QT_DECLARE_ORDERED_LITERAL_TYPE_4(...) \
0540     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0541 #define QT_DECLARE_ORDERED_LITERAL_TYPE_5(...) \
0542     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0543 #define QT_DECLARE_ORDERED_LITERAL_TYPE_6(...) \
0544     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0545 #define QT_DECLARE_ORDERED_LITERAL_TYPE_7(...) \
0546     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0547 #define QT_DECLARE_ORDERED_LITERAL_TYPE_8(...) \
0548     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0549 #define QT_DECLARE_ORDERED_LITERAL_TYPE_9(...) \
0550     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0551 
0552 #define Q_DECLARE_ORDERED_LITERAL_TYPE(...) \
0553     QT_OVERLOADED_MACRO(QT_DECLARE_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0554 
0555 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_1(Type) \
0556     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, Type, Type, /* non-constexpr */, noexcept(false), \
0557                                          /* no attributes */)
0558 
0559 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \
0560     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0561                                          noexcept(false), /* no attributes */) \
0562     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0563                                                   noexcept(false), /* no attributes */)
0564 
0565 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, ...) \
0566     QT_DECLARE_ORDERING_OPERATORS_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0567                                          noexcept(false), __VA_ARGS__) \
0568     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(AUTO, LeftType, RightType, /* non-constexpr */, \
0569                                                   noexcept(false), __VA_ARGS__)
0570 
0571 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_4(...) \
0572     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0573 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_5(...) \
0574     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0575 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_6(...) \
0576     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0577 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_7(...) \
0578     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0579 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_8(...) \
0580     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0581 #define QT_DECLARE_ORDERED_NON_NOEXCEPT_9(...) \
0582     QT_VA_ARGS_EXPAND(QT_DECLARE_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0583 
0584 #define Q_DECLARE_ORDERED_NON_NOEXCEPT(...) \
0585     QT_OVERLOADED_MACRO(QT_DECLARE_ORDERED_NON_NOEXCEPT, __VA_ARGS__)
0586 
0587 // Partial ordering operators
0588 #define QT_DECLARE_PARTIALLY_ORDERED_1(Type) \
0589     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */, \
0590                                          noexcept(true), /* no attributes */)
0591 
0592 #define QT_DECLARE_PARTIALLY_ORDERED_2(LeftType, RightType) \
0593     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
0594                                          noexcept(true), /* no attributes */) \
0595     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
0596                                                   /* non-constexpr */, noexcept(true), \
0597                                                   /* no attributes */)
0598 
0599 #define QT_DECLARE_PARTIALLY_ORDERED_3(LeftType, RightType, ...) \
0600     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
0601                                          noexcept(true), __VA_ARGS__) \
0602     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
0603                                                   /* non-constexpr */, noexcept(true), __VA_ARGS__)
0604 
0605 #define QT_DECLARE_PARTIALLY_ORDERED_4(...) \
0606     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0607 #define QT_DECLARE_PARTIALLY_ORDERED_5(...) \
0608     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0609 #define QT_DECLARE_PARTIALLY_ORDERED_6(...) \
0610     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0611 #define QT_DECLARE_PARTIALLY_ORDERED_7(...) \
0612     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0613 #define QT_DECLARE_PARTIALLY_ORDERED_8(...) \
0614     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0615 #define QT_DECLARE_PARTIALLY_ORDERED_9(...) \
0616     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_3(__VA_ARGS__))
0617 
0618 #define Q_DECLARE_PARTIALLY_ORDERED(...) \
0619     QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED, __VA_ARGS__)
0620 
0621 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_1(Type) \
0622     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, constexpr, noexcept(true), \
0623                                          /* no attributes */)
0624 
0625 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0626     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, \
0627                                          noexcept(true), /* no attributes */) \
0628     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \
0629                                                   noexcept(true), /* no attributes */)
0630 
0631 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, ...) \
0632     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr, noexcept(true), \
0633                                          __VA_ARGS__) \
0634     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr, \
0635                                                   noexcept(true), __VA_ARGS__)
0636 
0637 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_4(...) \
0638     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0639 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_5(...) \
0640     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0641 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_6(...) \
0642     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0643 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_7(...) \
0644     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0645 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_8(...) \
0646     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0647 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_9(...) \
0648     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0649 
0650 #define Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(...) \
0651     QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0652 
0653 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_1(Type) \
0654     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */, \
0655                                          noexcept(false), /* no attributes */)
0656 
0657 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \
0658     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
0659                                          noexcept(false), /* no attributes */) \
0660     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
0661                                                   /* non-constexpr */, noexcept(false), \
0662                                                   /* no attributes */)
0663 
0664 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, ...) \
0665     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */, \
0666                                          noexcept(false), __VA_ARGS__) \
0667     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, \
0668                                                   /* non-constexpr */, noexcept(false), __VA_ARGS__)
0669 
0670 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_4(...) \
0671     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0672 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_5(...) \
0673     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0674 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_6(...) \
0675     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0676 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_7(...) \
0677     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0678 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_8(...) \
0679     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0680 #define QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_9(...) \
0681     QT_VA_ARGS_EXPAND(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0682 
0683 #define Q_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT(...) \
0684     QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__)
0685 
0686 // Weak ordering operators
0687 #define QT_DECLARE_WEAKLY_ORDERED_1(Type) \
0688     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */, noexcept(true), \
0689                                          /* no attributes */)
0690 
0691 #define QT_DECLARE_WEAKLY_ORDERED_2(LeftType, RightType) \
0692     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0693                                          noexcept(true), /* no attributes */) \
0694     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0695                                                   noexcept(true), /* no attributes */)
0696 
0697 #define QT_DECLARE_WEAKLY_ORDERED_3(LeftType, RightType, ...) \
0698     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0699                                          noexcept(true), __VA_ARGS__) \
0700     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0701                                                   noexcept(true), __VA_ARGS__)
0702 
0703 #define QT_DECLARE_WEAKLY_ORDERED_4(...) \
0704     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0705 #define QT_DECLARE_WEAKLY_ORDERED_5(...) \
0706     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0707 #define QT_DECLARE_WEAKLY_ORDERED_6(...) \
0708     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0709 #define QT_DECLARE_WEAKLY_ORDERED_7(...) \
0710     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0711 #define QT_DECLARE_WEAKLY_ORDERED_8(...) \
0712     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0713 #define QT_DECLARE_WEAKLY_ORDERED_9(...) \
0714     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_3(__VA_ARGS__))
0715 
0716 #define Q_DECLARE_WEAKLY_ORDERED(...) \
0717     QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED, __VA_ARGS__)
0718 
0719 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_1(Type) \
0720     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, constexpr, noexcept(true), \
0721                                          /* no attributes */)
0722 
0723 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0724     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, \
0725                                          noexcept(true), /* no attributes */) \
0726     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \
0727                                                   noexcept(true), /* no attributes */)
0728 
0729 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, ...) \
0730     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr, noexcept(true), \
0731                                          __VA_ARGS__) \
0732     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr, \
0733                                                   noexcept(true), __VA_ARGS__)
0734 
0735 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_4(...) \
0736     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0737 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_5(...) \
0738     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0739 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_6(...) \
0740     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0741 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_7(...) \
0742     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0743 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_8(...) \
0744     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0745 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_9(...) \
0746     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0747 
0748 #define Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(...) \
0749     QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0750 
0751 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_1(Type) \
0752     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */, noexcept(false), \
0753                                          /* no attributes */)
0754 
0755 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \
0756     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0757                                          noexcept(false), /* no attributes */) \
0758     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0759                                                   noexcept(false), /* no attributes */)
0760 
0761 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, ...) \
0762     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0763                                          noexcept(false), __VA_ARGS__) \
0764     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */, \
0765                                                   noexcept(false), __VA_ARGS__)
0766 
0767 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_4(...) \
0768     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0769 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_5(...) \
0770     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0771 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_6(...) \
0772     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0773 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_7(...) \
0774     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0775 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_8(...) \
0776     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0777 #define QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_9(...) \
0778     QT_VA_ARGS_EXPAND(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0779 
0780 #define Q_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT(...) \
0781     QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__)
0782 
0783 // Strong ordering operators
0784 #define QT_DECLARE_STRONGLY_ORDERED_1(Type) \
0785     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */, \
0786                                          noexcept(true), /* no attributes */)
0787 
0788 #define QT_DECLARE_STRONGLY_ORDERED_2(LeftType, RightType) \
0789     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
0790                                          noexcept(true), /* no attributes */) \
0791     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
0792                                                   /* non-constexpr */, noexcept(true), \
0793                                                   /* no attributes */)
0794 
0795 #define QT_DECLARE_STRONGLY_ORDERED_3(LeftType, RightType, ...) \
0796     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
0797                                          noexcept(true), __VA_ARGS__) \
0798     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
0799                                                   /* non-constexpr */, noexcept(true), __VA_ARGS__)
0800 
0801 #define QT_DECLARE_STRONGLY_ORDERED_4(...) \
0802     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0803 #define QT_DECLARE_STRONGLY_ORDERED_5(...) \
0804     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0805 #define QT_DECLARE_STRONGLY_ORDERED_6(...) \
0806     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0807 #define QT_DECLARE_STRONGLY_ORDERED_7(...) \
0808     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0809 #define QT_DECLARE_STRONGLY_ORDERED_8(...) \
0810     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0811 #define QT_DECLARE_STRONGLY_ORDERED_9(...) \
0812     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_3(__VA_ARGS__))
0813 
0814 #define Q_DECLARE_STRONGLY_ORDERED(...) \
0815     QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED, __VA_ARGS__)
0816 
0817 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_1(Type) \
0818     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, constexpr, noexcept(true), \
0819                                          /* no attributes */)
0820 
0821 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0822     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, \
0823                                          noexcept(true), /* no attributes */) \
0824     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \
0825                                                   noexcept(true), /* no attributes */)
0826 
0827 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(LeftType, RightType, ...) \
0828     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr, noexcept(true), \
0829                                          __VA_ARGS__) \
0830     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr, \
0831                                                   noexcept(true), __VA_ARGS__)
0832 
0833 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_4(...) \
0834     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0835 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_5(...) \
0836     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0837 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_6(...) \
0838     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0839 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_7(...) \
0840     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0841 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_8(...) \
0842     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0843 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_9(...) \
0844     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_3(__VA_ARGS__))
0845 
0846 #define Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(...) \
0847     QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0848 
0849 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_1(Type) \
0850     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */, \
0851                                          noexcept(false), /* no attributes */)
0852 
0853 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_2(LeftType, RightType) \
0854     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
0855                                          noexcept(false), /* no attributes */) \
0856     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
0857                                                   /* non-constexpr */, noexcept(false), \
0858                                                   /* no attributes */)
0859 
0860 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(LeftType, RightType, ...) \
0861     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */, \
0862                                          noexcept(false), __VA_ARGS__) \
0863     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, \
0864                                                   /* non-constexpr */, noexcept(false), __VA_ARGS__)
0865 
0866 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_4(...) \
0867     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0868 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_5(...) \
0869     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0870 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_6(...) \
0871     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0872 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_7(...) \
0873     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0874 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_8(...) \
0875     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0876 #define QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_9(...) \
0877     QT_VA_ARGS_EXPAND(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT_3(__VA_ARGS__))
0878 
0879 #define Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(...) \
0880     QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT, __VA_ARGS__)
0881 
0882 namespace QtPrivate {
0883 
0884 template <typename T>
0885 constexpr bool IsIntegralType_v = std::numeric_limits<std::remove_const_t<T>>::is_specialized
0886                                   && std::numeric_limits<std::remove_const_t<T>>::is_integer;
0887 
0888 template <typename T>
0889 constexpr bool IsFloatType_v = std::is_floating_point_v<T>;
0890 
0891 #if QFLOAT16_IS_NATIVE
0892 template <>
0893 inline constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true;
0894 #endif
0895 
0896 } // namespace QtPrivate
0897 
0898 namespace QtOrderingPrivate {
0899 
0900 template <typename T, typename U>
0901 constexpr Qt::strong_ordering
0902 strongOrderingCompareDefaultImpl(T lhs, U rhs) noexcept
0903 {
0904 #ifdef __cpp_lib_three_way_comparison
0905     return lhs <=> rhs;
0906 #else
0907     if (lhs == rhs)
0908         return Qt::strong_ordering::equivalent;
0909     else if (lhs < rhs)
0910         return Qt::strong_ordering::less;
0911     else
0912         return Qt::strong_ordering::greater;
0913 #endif // __cpp_lib_three_way_comparison
0914 }
0915 
0916 } // namespace QtOrderingPrivate
0917 
0918 namespace Qt {
0919 
0920 template <typename T>
0921 using if_integral = std::enable_if_t<QtPrivate::IsIntegralType_v<T>, bool>;
0922 
0923 template <typename T>
0924 using if_floating_point = std::enable_if_t<QtPrivate::IsFloatType_v<T>, bool>;
0925 
0926 template <typename T, typename U>
0927 using if_compatible_pointers =
0928         std::enable_if_t<std::disjunction_v<std::is_same<T, U>,
0929                                             std::is_base_of<T, U>,
0930                                             std::is_base_of<U, T>>,
0931                          bool>;
0932 
0933 template <typename Enum>
0934 using if_enum = std::enable_if_t<std::is_enum_v<Enum>, bool>;
0935 
0936 template <typename LeftInt, typename RightInt,
0937           if_integral<LeftInt> = true,
0938           if_integral<RightInt> = true>
0939 constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept
0940 {
0941     static_assert(std::is_signed_v<LeftInt> == std::is_signed_v<RightInt>,
0942                   "Qt::compareThreeWay() does not allow mixed-sign comparison.");
0943 
0944 #ifdef __cpp_lib_three_way_comparison
0945     return lhs <=> rhs;
0946 #else
0947     if (lhs == rhs)
0948         return Qt::strong_ordering::equivalent;
0949     else if (lhs < rhs)
0950         return Qt::strong_ordering::less;
0951     else
0952         return Qt::strong_ordering::greater;
0953 #endif // __cpp_lib_three_way_comparison
0954 }
0955 
0956 template <typename LeftFloat, typename RightFloat,
0957           if_floating_point<LeftFloat> = true,
0958           if_floating_point<RightFloat> = true>
0959 constexpr Qt::partial_ordering compareThreeWay(LeftFloat lhs, RightFloat rhs) noexcept
0960 {
0961 QT_WARNING_PUSH
0962 QT_WARNING_DISABLE_FLOAT_COMPARE
0963 #ifdef __cpp_lib_three_way_comparison
0964     return lhs <=> rhs;
0965 #else
0966     if (lhs < rhs)
0967         return Qt::partial_ordering::less;
0968     else if (lhs > rhs)
0969         return Qt::partial_ordering::greater;
0970     else if (lhs == rhs)
0971         return Qt::partial_ordering::equivalent;
0972     else
0973         return Qt::partial_ordering::unordered;
0974 #endif // __cpp_lib_three_way_comparison
0975 QT_WARNING_POP
0976 }
0977 
0978 template <typename IntType, typename FloatType,
0979           if_integral<IntType> = true,
0980           if_floating_point<FloatType> = true>
0981 constexpr Qt::partial_ordering compareThreeWay(IntType lhs, FloatType rhs) noexcept
0982 {
0983     return compareThreeWay(FloatType(lhs), rhs);
0984 }
0985 
0986 template <typename FloatType, typename IntType,
0987           if_floating_point<FloatType> = true,
0988           if_integral<IntType> = true>
0989 constexpr Qt::partial_ordering compareThreeWay(FloatType lhs, IntType rhs) noexcept
0990 {
0991     return compareThreeWay(lhs, FloatType(rhs));
0992 }
0993 
0994 #if QT_DEPRECATED_SINCE(6, 8)
0995 
0996 template <typename LeftType, typename RightType,
0997           if_compatible_pointers<LeftType, RightType> = true>
0998 QT_DEPRECATED_VERSION_X_6_8("Wrap the pointers into Qt::totally_ordered_wrapper and use the respective overload instead.")
0999 constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightType *rhs) noexcept
1000 {
1001 #ifdef __cpp_lib_three_way_comparison
1002     return std::compare_three_way{}(lhs, rhs);
1003 #else
1004     if (lhs == rhs)
1005         return Qt::strong_ordering::equivalent;
1006     else if (std::less<>{}(lhs, rhs))
1007         return Qt::strong_ordering::less;
1008     else
1009         return Qt::strong_ordering::greater;
1010 #endif // __cpp_lib_three_way_comparison
1011 }
1012 
1013 template <typename T>
1014 QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.")
1015 constexpr Qt::strong_ordering compareThreeWay(const T *lhs, std::nullptr_t rhs) noexcept
1016 {
1017     return compareThreeWay(lhs, static_cast<const T *>(rhs));
1018 }
1019 
1020 template <typename T>
1021 QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.")
1022 constexpr Qt::strong_ordering compareThreeWay(std::nullptr_t lhs, const T *rhs) noexcept
1023 {
1024     return compareThreeWay(static_cast<const T *>(lhs), rhs);
1025 }
1026 
1027 #endif // QT_DEPRECATED_SINCE(6, 8)
1028 
1029 template <class Enum, if_enum<Enum> = true>
1030 constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept
1031 {
1032     return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs));
1033 }
1034 } // namespace Qt
1035 
1036 namespace QtOrderingPrivate {
1037 
1038 template <typename Head, typename...Tail, std::size_t...Is>
1039 constexpr std::tuple<Tail...> qt_tuple_pop_front_impl(const std::tuple<Head, Tail...> &t,
1040                                                       std::index_sequence<Is...>) noexcept
1041 {
1042     return std::tuple<Tail...>(std::get<Is + 1>(t)...);
1043 }
1044 
1045 template <typename Head, typename...Tail>
1046 constexpr std::tuple<Tail...> qt_tuple_pop_front(const std::tuple<Head, Tail...> &t) noexcept
1047 {
1048     return qt_tuple_pop_front_impl(t, std::index_sequence_for<Tail...>{});
1049 }
1050 
1051 template <typename LhsHead, typename...LhsTail, typename RhsHead, typename...RhsTail>
1052 constexpr auto compareThreeWayMulti(const std::tuple<LhsHead, LhsTail...> &lhs, // ie. not empty
1053                                     const std::tuple<RhsHead, RhsTail...> &rhs) noexcept
1054 {
1055     static_assert(sizeof...(LhsTail) == sizeof...(RhsTail),
1056                                                             // expanded together below, but provide a nicer error message:
1057                   "The tuple arguments have to have the same size.");
1058 
1059     using Qt::compareThreeWay;
1060     using R = std::common_type_t<
1061             decltype(compareThreeWay(std::declval<LhsHead>(), std::declval<RhsHead>())),
1062             decltype(compareThreeWay(std::declval<LhsTail>(), std::declval<RhsTail>()))...
1063             >;
1064 
1065     const auto &l = std::get<0>(lhs);
1066     const auto &r = std::get<0>(rhs);
1067     static_assert(noexcept(compareThreeWay(l, r)),
1068                   "This function requires all relational operators to be noexcept.");
1069     const auto res = compareThreeWay(l, r);
1070     if constexpr (sizeof...(LhsTail) > 0) {
1071         if (is_eq(res))
1072             return R{compareThreeWayMulti(qt_tuple_pop_front(lhs), qt_tuple_pop_front(rhs))};
1073     }
1074     return R{res};
1075 }
1076 
1077 } //QtOrderingPrivate
1078 
1079 namespace Qt {
1080 // A wrapper class that adapts the wrappee to use the strongly-ordered
1081 // <functional> function objects for implementing the relational operators.
1082 // Mostly useful to avoid UB on pointers (which it currently mandates P to be),
1083 // because all the comparison helpers (incl. std::compare_three_way on
1084 // std::tuple<T*>!) will use the language-level operators.
1085 //
1086 template <typename P>
1087 class totally_ordered_wrapper
1088 {
1089     static_assert(std::is_pointer_v<P>);
1090     using T = std::remove_pointer_t<P>;
1091 
1092     P ptr;
1093 public:
1094     totally_ordered_wrapper() noexcept = default;
1095     Q_IMPLICIT constexpr totally_ordered_wrapper(std::nullptr_t)
1096         // requires std::is_pointer_v<P>
1097         : totally_ordered_wrapper(P{nullptr}) {}
1098     explicit constexpr totally_ordered_wrapper(P p) noexcept : ptr(p) {}
1099 
1100     constexpr P get() const noexcept { return ptr; }
1101     constexpr void reset(P p) noexcept { ptr = p; }
1102     constexpr P operator->() const noexcept { return get(); }
1103     template <typename U = T, std::enable_if_t<!std::is_void_v<U>, bool> = true>
1104     constexpr U &operator*() const noexcept { return *get(); }
1105 
1106     explicit constexpr operator bool() const noexcept { return get(); }
1107 
1108 private:
1109     // TODO: Replace the constraints with std::common_type_t<P, U> when
1110     // a bug in VxWorks is fixed!
1111     template <typename T, typename U>
1112     using if_compatible_types =
1113             std::enable_if_t<std::conjunction_v<std::is_pointer<T>,
1114                                                 std::is_pointer<U>,
1115                                                 std::disjunction<std::is_convertible<T, U>,
1116                                                                  std::is_convertible<U, T>>>,
1117                              bool>;
1118 
1119 #define MAKE_RELOP(Ret, op, Op) \
1120     template <typename U = P, if_compatible_types<P, U> = true> \
1121     friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const totally_ordered_wrapper<U> &rhs) noexcept \
1122     { return std:: Op {}(lhs.ptr, rhs.get()); } \
1123     template <typename U = P, if_compatible_types<P, U> = true> \
1124     friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const U &rhs) noexcept \
1125     { return std:: Op {}(lhs.ptr, rhs    ); } \
1126     template <typename U = P, if_compatible_types<P, U> = true> \
1127     friend constexpr Ret operator op (const U &lhs, const totally_ordered_wrapper<P> &rhs) noexcept \
1128     { return std:: Op {}(lhs,     rhs.ptr); } \
1129     friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, std::nullptr_t) noexcept \
1130     { return std:: Op {}(lhs.ptr, P(nullptr)); } \
1131     friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \
1132     { return std:: Op {}(P(nullptr), rhs.ptr); } \
1133     /* end */
1134     MAKE_RELOP(bool, ==, equal_to<>)
1135     MAKE_RELOP(bool, !=, not_equal_to<>)
1136     MAKE_RELOP(bool, < , less<>)
1137     MAKE_RELOP(bool, <=, less_equal<>)
1138     MAKE_RELOP(bool, > , greater<>)
1139     MAKE_RELOP(bool, >=, greater_equal<>)
1140 #ifdef __cpp_lib_three_way_comparison
1141     MAKE_RELOP(auto, <=>, compare_three_way)
1142 #endif
1143 #undef MAKE_RELOP
1144     friend void qt_ptr_swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept
1145     { qt_ptr_swap(lhs.ptr, rhs.ptr); }
1146     friend void swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept
1147     { qt_ptr_swap(lhs, rhs); }
1148     friend size_t qHash(totally_ordered_wrapper key, size_t seed = 0) noexcept
1149     { return qHash(key.ptr, seed); }
1150 };
1151 
1152 template <typename T, typename U, if_compatible_pointers<T, U> = true>
1153 constexpr Qt::strong_ordering
1154 compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<U*> rhs) noexcept
1155 {
1156     return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
1157 }
1158 
1159 template <typename T, typename U, if_compatible_pointers<T, U> = true>
1160 constexpr Qt::strong_ordering
1161 compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, U *rhs) noexcept
1162 {
1163     return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
1164 }
1165 
1166 template <typename T, typename U, if_compatible_pointers<T, U> = true>
1167 constexpr Qt::strong_ordering
1168 compareThreeWay(U *lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept
1169 {
1170     return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
1171 }
1172 
1173 template <typename T>
1174 constexpr Qt::strong_ordering
1175 compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) noexcept
1176 {
1177     return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
1178 }
1179 
1180 template <typename T>
1181 constexpr Qt::strong_ordering
1182 compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept
1183 {
1184     return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
1185 }
1186 
1187 } //Qt
1188 
1189 template <typename P>
1190 class QTypeInfo<Qt::totally_ordered_wrapper<P>> : public QTypeInfo<P> {};
1191 
1192 namespace QtOrderingPrivate {
1193 
1194 QT_WARNING_PUSH
1195 QT_WARNING_DISABLE_DEPRECATED // don't warn _here_ in case we hit the deprecated ptr/ptr overloads
1196 
1197 namespace CompareThreeWayTester {
1198 
1199 using Qt::compareThreeWay;
1200 
1201 template <typename T>
1202 using WrappedType = std::conditional_t<std::is_pointer_v<T>, Qt::totally_ordered_wrapper<T>, T>;
1203 
1204 // Check if compareThreeWay is implemented for the (LT, RT) argument
1205 // pair.
1206 template <typename LT, typename RT, typename = void>
1207 struct HasCompareThreeWay : std::false_type {};
1208 
1209 template <typename LT, typename RT>
1210 struct HasCompareThreeWay<
1211         LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))>
1212     > : std::true_type {};
1213 
1214 template <typename LT, typename RT>
1215 struct HasCompareThreeWay<
1216         LT*, RT*,
1217         std::void_t<decltype(compareThreeWay(std::declval<WrappedType<LT>>(),
1218                                              std::declval<WrappedType<RT>>()))>
1219     > : std::true_type {};
1220 
1221 template <typename LT, typename RT>
1222 constexpr inline bool hasCompareThreeWay_v = HasCompareThreeWay<LT, RT>::value;
1223 
1224 // Check if the operation is noexcept. We have two different overloads,
1225 // depending on the available compareThreeWay() implementation.
1226 // Both are declared, but not implemented. To be used only in unevaluated
1227 // context.
1228 
1229 template <typename LT, typename RT,
1230           std::enable_if_t<hasCompareThreeWay_v<LT, RT>, bool> = true>
1231 constexpr bool compareThreeWayNoexcept() noexcept
1232 { return noexcept(compareThreeWay(std::declval<LT>(), std::declval<RT>())); }
1233 
1234 template <typename LT, typename RT,
1235           std::enable_if_t<std::conjunction_v<std::negation<HasCompareThreeWay<LT, RT>>,
1236                                               HasCompareThreeWay<RT, LT>>,
1237                            bool> = true>
1238 constexpr bool compareThreeWayNoexcept() noexcept
1239 { return noexcept(compareThreeWay(std::declval<RT>(), std::declval<LT>())); }
1240 
1241 } // namespace CompareThreeWayTester
1242 
1243 QT_WARNING_POP // QT_WARNING_DISABLE_DEPRECATED
1244 
1245 #ifdef __cpp_lib_three_way_comparison
1246 [[maybe_unused]] inline constexpr struct { /* Niebloid */
1247     template <typename LT, typename RT = LT>
1248     [[maybe_unused]] constexpr auto operator()(const LT &lhs, const RT &rhs) const
1249     {
1250         // like [expos.only.entity]/2
1251         if constexpr (QTypeTraits::has_operator_compare_three_way_with_v<LT, RT>) {
1252             return lhs <=> rhs;
1253         } else {
1254             if (lhs < rhs)
1255                 return std::weak_ordering::less;
1256             if (rhs < lhs)
1257                 return std::weak_ordering::greater;
1258             return std::weak_ordering::equivalent;
1259         }
1260     }
1261 } synthThreeWay;
1262 
1263 template <typename Container, typename T>
1264 using if_has_op_less_or_op_compare_three_way =
1265         std::enable_if_t<
1266                 std::disjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>,
1267                                    QTypeTraits::has_operator_compare_three_way<T>>,
1268                 bool>;
1269 #endif // __cpp_lib_three_way_comparison
1270 
1271 // These checks do not use Qt::compareThreeWay(), so only work for user-defined
1272 // compareThreeWay() helper functions.
1273 // We cannot use the same condition as in CompareThreeWayTester::hasCompareThreeWay,
1274 // because GCC seems to cache and re-use the result.
1275 // Created https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117174
1276 // For now, modify the condition a bit without changing its meaning.
1277 template <typename LT, typename RT = LT, typename = void>
1278 struct HasCustomCompareThreeWay : std::false_type {};
1279 
1280 template <typename LT, typename RT>
1281 struct HasCustomCompareThreeWay<
1282         LT, RT,
1283         std::void_t<decltype(is_eq(compareThreeWay(std::declval<LT>(), std::declval<RT>())))>
1284     > : std::true_type {};
1285 
1286 template <typename InputIt1, typename InputIt2, typename Compare>
1287 auto lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1,
1288                                     InputIt2 first2, InputIt2 last2,
1289                                     Compare cmp)
1290 {
1291     using R = decltype(cmp(*first1, *first2));
1292 
1293     while (first1 != last1) {
1294         if (first2 == last2)
1295             return R::greater;
1296         const auto r = cmp(*first1, *first2);
1297         if (is_neq(r))
1298             return r;
1299         ++first1;
1300         ++first2;
1301     }
1302     return first2 == last2 ? R::equivalent : R::less;
1303 }
1304 
1305 template <typename InputIt1, typename InputIt2>
1306 auto lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1,
1307                                     InputIt2 first2, InputIt2 last2)
1308 {
1309     using LT = typename std::iterator_traits<InputIt1>::value_type;
1310     using RT = typename std::iterator_traits<InputIt2>::value_type;
1311 
1312     // if LT && RT are pointers, and there is no user-defined compareThreeWay()
1313     // operation for the pointers, we need to wrap them into
1314     // Qt::totally_ordered_wrapper.
1315     constexpr bool UseWrapper =
1316             std::conjunction_v<std::is_pointer<LT>, std::is_pointer<RT>,
1317                                std::negation<HasCustomCompareThreeWay<LT, RT>>,
1318                                std::negation<HasCustomCompareThreeWay<RT, LT>>>;
1319     using WrapLT = std::conditional_t<UseWrapper,
1320                                       Qt::totally_ordered_wrapper<LT>,
1321                                       const LT &>;
1322     using WrapRT = std::conditional_t<UseWrapper,
1323                                       Qt::totally_ordered_wrapper<RT>,
1324                                       const RT &>;
1325 
1326     auto cmp = [](LT const &lhs, RT const &rhs) {
1327         using Qt::compareThreeWay;
1328         namespace Test = QtOrderingPrivate::CompareThreeWayTester;
1329         // Need this because the user might provide only
1330         // compareThreeWay(LT, RT), but not the reversed version.
1331         if constexpr (Test::hasCompareThreeWay_v<WrapLT, WrapRT>)
1332             return compareThreeWay(WrapLT(lhs), WrapRT(rhs));
1333         else
1334             return QtOrderingPrivate::reversed(compareThreeWay(WrapRT(rhs), WrapLT(lhs)));
1335     };
1336     return lexicographicalCompareThreeWay(first1, last1, first2, last2, cmp);
1337 }
1338 
1339 } // namespace QtOrderingPrivate
1340 
1341 namespace Qt {
1342 
1343 template <typename T, typename U>
1344 using if_has_qt_compare_three_way =
1345         std::enable_if_t<
1346             std::disjunction_v<QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<T, U>,
1347                                QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<U, T>>,
1348         bool>;
1349 
1350 } // namespace Qt
1351 
1352 QT_END_NAMESPACE
1353 
1354 namespace std {
1355     template <typename P>
1356     struct hash<QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>>
1357     {
1358         using argument_type = QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>;
1359         using result_type = size_t;
1360         constexpr result_type operator()(argument_type w) const noexcept
1361         { return std::hash<P>{}(w.get()); }
1362     };
1363 }
1364 
1365 #endif // QCOMPAREHELPERS_H