Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qcomparehelpers.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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/qoverload.h>
0018 #include <QtCore/qttypetraits.h>
0019 #include <QtCore/qtypes.h>
0020 
0021 #ifdef __cpp_lib_three_way_comparison
0022 #include <compare>
0023 #endif
0024 #include <QtCore/q20type_traits.h>
0025 
0026 #include <functional> // std::less
0027 
0028 QT_BEGIN_NAMESPACE
0029 
0030 class QPartialOrdering;
0031 
0032 namespace QtOrderingPrivate {
0033 #ifdef __cpp_lib_three_way_comparison
0034 
0035 template <typename QtOrdering> struct StdOrdering;
0036 template <typename StdOrdering> struct QtOrdering;
0037 
0038 #define QT_STD_MAP(x) \
0039     template <> struct StdOrdering< Qt::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
0040     template <> struct StdOrdering<std::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
0041     template <> struct  QtOrdering<std::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
0042     template <> struct  QtOrdering< Qt::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
0043     /* end */
0044 QT_STD_MAP(partial)
0045 QT_STD_MAP(weak)
0046 QT_STD_MAP(strong)
0047 #undef QT_STD_MAP
0048 
0049 template <> struct StdOrdering<QPartialOrdering> : q20::type_identity<std::partial_ordering> {};
0050 template <> struct  QtOrdering<QPartialOrdering> : q20::type_identity< Qt::partial_ordering> {};
0051 
0052 template <typename In> constexpr auto to_std(In in) noexcept
0053     -> typename QtOrderingPrivate::StdOrdering<In>::type
0054 { return in; }
0055 
0056 template <typename In> constexpr auto to_Qt(In in) noexcept
0057     -> typename QtOrderingPrivate::QtOrdering<In>::type
0058 { return in; }
0059 
0060 #endif // __cpp_lib_three_way_comparison
0061 } // namespace QtOrderingPrivate
0062 
0063 /*
0064     For all the macros these parameter names are used:
0065     * LeftType - the type of the left operand of the comparison
0066     * RightType - the type of the right operand of the comparison
0067     * Constexpr - must be either constexpr or empty. Defines whether the
0068                   operator is constexpr or not
0069 
0070     The macros require two helper functions. For operators to be constexpr,
0071     these must be constexpr, too. Additionally, other attributes (like
0072     Q_<Module>_EXPORT, Q_DECL_CONST_FUNCTION, etc) can be applied to them.
0073     Aside from that, their declaration should match:
0074         bool comparesEqual(LeftType, RightType) noexcept;
0075         ReturnType compareThreeWay(LeftType, RightType) noexcept;
0076 
0077     The ReturnType can be one of Qt::{partial,weak,strong}_ordering. The actual
0078     type depends on the macro being used.
0079     It makes sense to define the helper functions as hidden friends of the
0080     class, so that they could be found via ADL, and don't participate in
0081     unintended implicit conversions.
0082 */
0083 
0084 // Seems that qdoc uses C++20 even when Qt is compiled in C++17 mode.
0085 // Or at least it defines __cpp_lib_three_way_comparison.
0086 // Let qdoc see only the C++17 operators for now, because that's what our docs
0087 // currently describe.
0088 #if defined(__cpp_lib_three_way_comparison) && !defined(Q_QDOC)
0089 // C++20 - provide operator==() for equality, and operator<=>() for ordering
0090 
0091 #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr) \
0092     friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) \
0093         noexcept(noexcept(comparesEqual(lhs, rhs))) \
0094     { return comparesEqual(lhs, rhs); }
0095 
0096 #define QT_DECLARE_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr) \
0097     friend Constexpr std::strong_ordering \
0098     operator<=>(LeftType const &lhs, RightType const &rhs) \
0099         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0100     { \
0101         return compareThreeWay(lhs, rhs); \
0102     }
0103 
0104 #define QT_DECLARE_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr) \
0105     friend Constexpr std::weak_ordering \
0106     operator<=>(LeftType const &lhs, RightType const &rhs) \
0107         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0108     { \
0109         return compareThreeWay(lhs, rhs); \
0110     }
0111 
0112 #define QT_DECLARE_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr) \
0113     friend Constexpr std::partial_ordering \
0114     operator<=>(LeftType const &lhs, RightType const &rhs) \
0115         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0116     { \
0117         return compareThreeWay(lhs, rhs); \
0118     }
0119 
0120 #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingType, LeftType, RightType, Constexpr) \
0121     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr) \
0122     QT_DECLARE_3WAY_HELPER_ ## OrderingType (LeftType, RightType, Constexpr)
0123 
0124 #ifdef Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
0125 
0126 // define reversed versions of the operators manually, because buggy MSVC versions do not do it
0127 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr) \
0128     friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) \
0129         noexcept(noexcept(comparesEqual(rhs, lhs))) \
0130     { return comparesEqual(rhs, lhs); }
0131 
0132 #define QT_DECLARE_REVERSED_3WAY_HELPER_STRONG(LeftType, RightType, Constexpr) \
0133     friend Constexpr std::strong_ordering \
0134     operator<=>(RightType const &lhs, LeftType const &rhs) \
0135         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0136     { \
0137         const auto r = compareThreeWay(rhs, lhs); \
0138         if (r > 0) return std::strong_ordering::less; \
0139         if (r < 0) return std::strong_ordering::greater; \
0140         return r; \
0141     }
0142 
0143 #define QT_DECLARE_REVERSED_3WAY_HELPER_WEAK(LeftType, RightType, Constexpr) \
0144     friend Constexpr std::weak_ordering \
0145     operator<=>(RightType const &lhs, LeftType const &rhs) \
0146         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0147     { \
0148         const auto r = compareThreeWay(rhs, lhs); \
0149         if (r > 0) return std::weak_ordering::less; \
0150         if (r < 0) return std::weak_ordering::greater; \
0151         return r; \
0152     }
0153 
0154 #define QT_DECLARE_REVERSED_3WAY_HELPER_PARTIAL(LeftType, RightType, Constexpr) \
0155     friend Constexpr std::partial_ordering \
0156     operator<=>(RightType const &lhs, LeftType const &rhs) \
0157         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0158     { \
0159         const auto r = compareThreeWay(rhs, lhs); \
0160         if (r > 0) return std::partial_ordering::less; \
0161         if (r < 0) return std::partial_ordering::greater; \
0162         return r; \
0163     }
0164 
0165 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
0166                                                       Constexpr) \
0167     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr) \
0168     QT_DECLARE_REVERSED_3WAY_HELPER_ ## OrderingString (LeftType, RightType, Constexpr)
0169 
0170 #else
0171 
0172 // dummy macros for C++17 compatibility, reversed operators are generated by the compiler
0173 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr)
0174 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, Constexpr)
0175 
0176 #endif // Q_COMPILER_LACKS_THREE_WAY_COMPARE_SYMMETRY
0177 
0178 #else
0179 // C++17 - provide operator==() and operator!=() for equality,
0180 // and all 4 comparison operators for ordering
0181 
0182 #define QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr) \
0183     friend Constexpr bool operator==(LeftType const &lhs, RightType const &rhs) \
0184         noexcept(noexcept(comparesEqual(lhs, rhs))) \
0185     { return comparesEqual(lhs, rhs); } \
0186     friend Constexpr bool operator!=(LeftType const &lhs, RightType const &rhs) \
0187         noexcept(noexcept(comparesEqual(lhs, rhs))) \
0188     { return !comparesEqual(lhs, rhs); }
0189 
0190 // Helpers for reversed comparison, using the existing comparesEqual() function.
0191 #define QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr) \
0192     friend Constexpr bool operator==(RightType const &lhs, LeftType const &rhs) \
0193         noexcept(noexcept(comparesEqual(rhs, lhs))) \
0194     { return comparesEqual(rhs, lhs); } \
0195     friend Constexpr bool operator!=(RightType const &lhs, LeftType const &rhs) \
0196         noexcept(noexcept(comparesEqual(rhs, lhs))) \
0197     { return !comparesEqual(rhs, lhs); }
0198 
0199 #define QT_DECLARE_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr) \
0200     friend Constexpr bool operator<(LeftType const &lhs, RightType const &rhs) \
0201         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0202     { return compareThreeWay(lhs, rhs) < 0; } \
0203     friend Constexpr bool operator>(LeftType const &lhs, RightType const &rhs) \
0204         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0205     { return compareThreeWay(lhs, rhs) > 0; } \
0206     friend Constexpr bool operator<=(LeftType const &lhs, RightType const &rhs) \
0207         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0208     { return compareThreeWay(lhs, rhs) <= 0; } \
0209     friend Constexpr bool operator>=(LeftType const &lhs, RightType const &rhs) \
0210         noexcept(noexcept(compareThreeWay(lhs, rhs))) \
0211     { return compareThreeWay(lhs, rhs) >= 0; }
0212 
0213 #define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr) \
0214     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr)
0215 
0216 #define QT_DECLARE_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr) \
0217     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, Constexpr)
0218 
0219 #define QT_DECLARE_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr) \
0220     QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, Constexpr)
0221 
0222 #define QT_DECLARE_ORDERING_OPERATORS_HELPER(OrderingString, LeftType, RightType, Constexpr) \
0223     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, Constexpr) \
0224     QT_DECLARE_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr)
0225 
0226 // Helpers for reversed ordering, using the existing compareThreeWay() function.
0227 #define QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(OrderingType, LeftType, RightType, Constexpr) \
0228     friend Constexpr bool operator<(RightType const &lhs, LeftType const &rhs) \
0229         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0230     { return compareThreeWay(rhs, lhs) > 0; } \
0231     friend Constexpr bool operator>(RightType const &lhs, LeftType const &rhs) \
0232         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0233     { return compareThreeWay(rhs, lhs) < 0; } \
0234     friend Constexpr bool operator<=(RightType const &lhs, LeftType const &rhs) \
0235         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0236     { return compareThreeWay(rhs, lhs) >= 0; } \
0237     friend Constexpr bool operator>=(RightType const &lhs, LeftType const &rhs) \
0238         noexcept(noexcept(compareThreeWay(rhs, lhs))) \
0239     { return compareThreeWay(rhs, lhs) <= 0; }
0240 
0241 #define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr) \
0242     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr)
0243 
0244 #define QT_DECLARE_REVERSED_ORDERING_HELPER_WEAK(LeftType, RightType, Constexpr) \
0245     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::weak_ordering, LeftType, RightType, Constexpr)
0246 
0247 #define QT_DECLARE_REVERSED_ORDERING_HELPER_STRONG(LeftType, RightType, Constexpr) \
0248     QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::strong_ordering, LeftType, RightType, Constexpr)
0249 
0250 #define QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(OrderingString, LeftType, RightType, \
0251                                                       Constexpr) \
0252     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, Constexpr) \
0253     QT_DECLARE_REVERSED_ORDERING_HELPER_ ## OrderingString (LeftType, RightType, Constexpr)
0254 
0255 #endif // __cpp_lib_three_way_comparison
0256 
0257 /* Public API starts here */
0258 
0259 // Equality operators
0260 #define QT_DECLARE_EQUALITY_COMPARABLE_1(Type) \
0261     QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, /* non-constexpr */)
0262 
0263 #define QT_DECLARE_EQUALITY_COMPARABLE_2(LeftType, RightType) \
0264     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, /* non-constexpr */) \
0265     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, /* non-constexpr */)
0266 
0267 #define Q_DECLARE_EQUALITY_COMPARABLE(...) \
0268     QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE, __VA_ARGS__)
0269 
0270 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_1(Type) \
0271     QT_DECLARE_EQUALITY_OPERATORS_HELPER(Type, Type, constexpr)
0272 
0273 #define QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE_2(LeftType, RightType) \
0274     QT_DECLARE_EQUALITY_OPERATORS_HELPER(LeftType, RightType, constexpr) \
0275     QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(LeftType, RightType, constexpr)
0276 
0277 #define Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(...) \
0278     QT_OVERLOADED_MACRO(QT_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE, __VA_ARGS__)
0279 
0280 // Partial ordering operators
0281 #define QT_DECLARE_PARTIALLY_ORDERED_1(Type) \
0282     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, /* non-constexpr */)
0283 
0284 #define QT_DECLARE_PARTIALLY_ORDERED_2(LeftType, RightType) \
0285     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */) \
0286     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, /* non-constexpr */)
0287 
0288 #define Q_DECLARE_PARTIALLY_ORDERED(...) \
0289     QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED, __VA_ARGS__)
0290 
0291 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_1(Type) \
0292     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, Type, Type, constexpr)
0293 
0294 #define QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0295     QT_DECLARE_ORDERING_OPERATORS_HELPER(PARTIAL, LeftType, RightType, constexpr) \
0296     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(PARTIAL, LeftType, RightType, constexpr)
0297 
0298 #define Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE(...) \
0299     QT_OVERLOADED_MACRO(QT_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0300 
0301 // Weak ordering operators
0302 #define QT_DECLARE_WEAKLY_ORDERED_1(Type) \
0303     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, /* non-constexpr */)
0304 
0305 #define QT_DECLARE_WEAKLY_ORDERED_2(LeftType, RightType) \
0306     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, /* non-constexpr */) \
0307     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, /* non-constexpr */)
0308 
0309 #define Q_DECLARE_WEAKLY_ORDERED(...) \
0310     QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED, __VA_ARGS__)
0311 
0312 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_1(Type) \
0313     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, Type, Type, constexpr)
0314 
0315 #define QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0316     QT_DECLARE_ORDERING_OPERATORS_HELPER(WEAK, LeftType, RightType, constexpr) \
0317     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(WEAK, LeftType, RightType, constexpr)
0318 
0319 #define Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(...) \
0320     QT_OVERLOADED_MACRO(QT_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0321 
0322 // Strong ordering operators
0323 #define QT_DECLARE_STRONGLY_ORDERED_1(Type) \
0324     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, /* non-constexpr */)
0325 
0326 #define QT_DECLARE_STRONGLY_ORDERED_2(LeftType, RightType) \
0327     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, /* non-constexpr */) \
0328     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, /* non-constexpr */)
0329 
0330 #define Q_DECLARE_STRONGLY_ORDERED(...) \
0331     QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED, __VA_ARGS__)
0332 
0333 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_1(Type) \
0334     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, Type, Type, constexpr)
0335 
0336 #define QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE_2(LeftType, RightType) \
0337     QT_DECLARE_ORDERING_OPERATORS_HELPER(STRONG, LeftType, RightType, constexpr) \
0338     QT_DECLARE_ORDERING_OPERATORS_REVERSED_HELPER(STRONG, LeftType, RightType, constexpr)
0339 
0340 #define Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(...) \
0341     QT_OVERLOADED_MACRO(QT_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE, __VA_ARGS__)
0342 
0343 namespace QtPrivate {
0344 
0345 template <typename T>
0346 constexpr bool IsIntegralType_v = std::numeric_limits<std::remove_const_t<T>>::is_specialized
0347                                   && std::numeric_limits<std::remove_const_t<T>>::is_integer;
0348 
0349 template <typename T>
0350 constexpr bool IsFloatType_v = std::is_floating_point_v<T>;
0351 
0352 #if QFLOAT16_IS_NATIVE
0353 template <>
0354 constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true;
0355 #endif
0356 
0357 } // namespace QtPrivate
0358 
0359 namespace Qt {
0360 
0361 template <typename T>
0362 using if_integral = std::enable_if_t<QtPrivate::IsIntegralType_v<T>, bool>;
0363 
0364 template <typename T>
0365 using if_floating_point = std::enable_if_t<QtPrivate::IsFloatType_v<T>, bool>;
0366 
0367 template <typename T, typename U>
0368 using if_compatible_pointers =
0369         std::enable_if_t<std::disjunction_v<std::is_same<T, U>,
0370                                             std::is_base_of<T, U>,
0371                                             std::is_base_of<U, T>>,
0372                          bool>;
0373 
0374 template <typename Enum>
0375 using if_enum = std::enable_if_t<std::is_enum_v<Enum>, bool>;
0376 
0377 template <typename LeftInt, typename RightInt,
0378           if_integral<LeftInt> = true,
0379           if_integral<RightInt> = true>
0380 constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept
0381 {
0382     static_assert(std::is_signed_v<LeftInt> == std::is_signed_v<RightInt>,
0383                   "Qt::compareThreeWay() does not allow mixed-sign comparison.");
0384 
0385 #ifdef __cpp_lib_three_way_comparison
0386     return lhs <=> rhs;
0387 #else
0388     if (lhs == rhs)
0389         return Qt::strong_ordering::equivalent;
0390     else if (lhs < rhs)
0391         return Qt::strong_ordering::less;
0392     else
0393         return Qt::strong_ordering::greater;
0394 #endif // __cpp_lib_three_way_comparison
0395 }
0396 
0397 template <typename LeftFloat, typename RightFloat,
0398           if_floating_point<LeftFloat> = true,
0399           if_floating_point<RightFloat> = true>
0400 constexpr Qt::partial_ordering compareThreeWay(LeftFloat lhs, RightFloat rhs) noexcept
0401 {
0402 QT_WARNING_PUSH
0403 QT_WARNING_DISABLE_FLOAT_COMPARE
0404 #ifdef __cpp_lib_three_way_comparison
0405     return lhs <=> rhs;
0406 #else
0407     if (lhs < rhs)
0408         return Qt::partial_ordering::less;
0409     else if (lhs > rhs)
0410         return Qt::partial_ordering::greater;
0411     else if (lhs == rhs)
0412         return Qt::partial_ordering::equivalent;
0413     else
0414         return Qt::partial_ordering::unordered;
0415 #endif // __cpp_lib_three_way_comparison
0416 QT_WARNING_POP
0417 }
0418 
0419 template <typename IntType, typename FloatType,
0420           if_integral<IntType> = true,
0421           if_floating_point<FloatType> = true>
0422 constexpr Qt::partial_ordering compareThreeWay(IntType lhs, FloatType rhs) noexcept
0423 {
0424     return compareThreeWay(FloatType(lhs), rhs);
0425 }
0426 
0427 template <typename FloatType, typename IntType,
0428           if_floating_point<FloatType> = true,
0429           if_integral<IntType> = true>
0430 constexpr Qt::partial_ordering compareThreeWay(FloatType lhs, IntType rhs) noexcept
0431 {
0432     return compareThreeWay(lhs, FloatType(rhs));
0433 }
0434 
0435 template <typename LeftType, typename RightType,
0436           if_compatible_pointers<LeftType, RightType> = true>
0437 constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightType *rhs) noexcept
0438 {
0439 #ifdef __cpp_lib_three_way_comparison
0440     return std::compare_three_way{}(lhs, rhs);
0441 #else
0442     if (lhs == rhs)
0443         return Qt::strong_ordering::equivalent;
0444     else if (std::less<>{}(lhs, rhs))
0445         return Qt::strong_ordering::less;
0446     else
0447         return Qt::strong_ordering::greater;
0448 #endif // __cpp_lib_three_way_comparison
0449 }
0450 
0451 template <typename T>
0452 constexpr Qt::strong_ordering compareThreeWay(const T *lhs, std::nullptr_t rhs) noexcept
0453 {
0454     return compareThreeWay(lhs, static_cast<const T *>(rhs));
0455 }
0456 
0457 template <typename T>
0458 constexpr Qt::strong_ordering compareThreeWay(std::nullptr_t lhs, const T *rhs) noexcept
0459 {
0460     return compareThreeWay(static_cast<const T *>(lhs), rhs);
0461 }
0462 
0463 template <class Enum, if_enum<Enum> = true>
0464 constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept
0465 {
0466     return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs));
0467 }
0468 
0469 } // namespace Qt
0470 
0471 QT_END_NAMESPACE
0472 
0473 #endif // QCOMPAREHELPERS_H