Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-12 09:23:16

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