Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 09:05:59

0001 // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
0002 // Copyright (C) 2023 The Qt Company Ltd.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QCOMPARE_H
0006 #define QCOMPARE_H
0007 
0008 #if 0
0009 #pragma qt_class(QtCompare)
0010 #endif
0011 
0012 #include <QtCore/qglobal.h>
0013 #include <QtCore/qcompare_impl.h>
0014 #include <QtCore/qstdlibdetection.h>
0015 
0016 #ifdef __cpp_lib_bit_cast
0017 #include <bit>
0018 #endif
0019 #ifdef __cpp_lib_three_way_comparison
0020 #include <compare>
0021 #endif
0022 
0023 QT_BEGIN_NAMESPACE
0024 
0025 namespace QtPrivate {
0026 using CompareUnderlyingType = qint8;
0027 constexpr CompareUnderlyingType LegacyUncomparableValue = -127; // historic Qt value
0028 
0029 // [cmp.categories.pre] / 1
0030 enum class Ordering : CompareUnderlyingType
0031 {
0032     Equal = 0,
0033     Equivalent = Equal,
0034     Less = -1,
0035     Greater = 1
0036 };
0037 
0038 enum class Uncomparable : CompareUnderlyingType
0039 {
0040     Unordered =
0041         #if   defined(Q_STL_LIBCPP)
0042                 -127
0043         #elif defined(Q_STL_LIBSTDCPP)
0044                    2
0045         #elif defined(Q_STL_MSSTL)
0046                 -128
0047         #elif defined(Q_STL_DINKUMWARE) || \
0048               defined(Q_STL_ROGUEWAVE)  || \
0049               defined(Q_STL_STLPORT)    || \
0050               defined(Q_STL_SGI)
0051                 QtPrivate::LegacyUncomparableValue
0052         // We haven't seen C++20 of these libraries, so we don't promise BC there.
0053         # ifdef __cpp_lib_three_way_comparison
0054         #  error Please report the numeric value of std::partial_ordering::unordered in your STL in a bug report.
0055         # endif
0056         #else
0057         #   error Please handle any newly-added Q_STL_ checks in the above ifdef-ery.
0058         #endif
0059 };
0060 
0061 } // namespace QtPrivate
0062 
0063 namespace QtOrderingPrivate {
0064 
0065 template <typename O>
0066 constexpr O reversed(O o) noexcept
0067 {
0068     // https://eel.is/c++draft/cmp.partialord#5
0069     return is_lt(o) ? O::greater :
0070            is_gt(o) ? O::less :
0071            /*else*/ o ;
0072 }
0073 
0074 } // namespace QtOrderingPrivate
0075 
0076 namespace Qt {
0077 
0078 class weak_ordering;
0079 class strong_ordering;
0080 
0081 class partial_ordering
0082 {
0083 public:
0084     static const partial_ordering less;
0085     static const partial_ordering equivalent;
0086     static const partial_ordering greater;
0087     static const partial_ordering unordered;
0088 
0089     friend constexpr bool operator==(partial_ordering lhs,
0090                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0091     { return lhs.isOrdered() && lhs.m_order == 0; }
0092 
0093     friend constexpr bool operator!=(partial_ordering lhs,
0094                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0095     { return !lhs.isOrdered() || lhs.m_order != 0; }
0096 
0097     friend constexpr bool operator< (partial_ordering lhs,
0098                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0099     { return lhs.isOrdered() && lhs.m_order <  0; }
0100 
0101     friend constexpr bool operator<=(partial_ordering lhs,
0102                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0103     { return lhs.isOrdered() && lhs.m_order <= 0; }
0104 
0105     friend constexpr bool operator> (partial_ordering lhs,
0106                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0107     { return lhs.isOrdered() && lhs.m_order >  0; }
0108 
0109     friend constexpr bool operator>=(partial_ordering lhs,
0110                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0111     { return lhs.isOrdered() && lhs.m_order >= 0; }
0112 
0113 
0114     friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
0115                                      partial_ordering rhs) noexcept
0116     { return rhs.isOrdered() && 0 == rhs.m_order; }
0117 
0118     friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
0119                                      partial_ordering rhs) noexcept
0120     { return !rhs.isOrdered() || 0 != rhs.m_order; }
0121 
0122     friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
0123                                      partial_ordering rhs) noexcept
0124     { return rhs.isOrdered() && 0 <  rhs.m_order; }
0125 
0126     friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
0127                                      partial_ordering rhs) noexcept
0128     { return rhs.isOrdered() && 0 <= rhs.m_order; }
0129 
0130     friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
0131                                      partial_ordering rhs) noexcept
0132     { return rhs.isOrdered() && 0 >  rhs.m_order; }
0133 
0134     friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
0135                                      partial_ordering rhs) noexcept
0136     { return rhs.isOrdered() && 0 >= rhs.m_order; }
0137 
0138 
0139 #ifdef __cpp_lib_three_way_comparison
0140     friend constexpr std::partial_ordering
0141     operator<=>(partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
0142     { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
0143 
0144     friend constexpr std::partial_ordering
0145     operator<=>(QtPrivate::CompareAgainstLiteralZero, partial_ordering rhs) noexcept
0146     { return QtOrderingPrivate::reversed(rhs); }
0147 #endif // __cpp_lib_three_way_comparison
0148 
0149 
0150     friend constexpr bool operator==(partial_ordering lhs, partial_ordering rhs) noexcept
0151     { return lhs.m_order == rhs.m_order; }
0152 
0153     friend constexpr bool operator!=(partial_ordering lhs, partial_ordering rhs) noexcept
0154     { return lhs.m_order != rhs.m_order; }
0155 
0156 #ifdef __cpp_lib_three_way_comparison
0157     constexpr Q_IMPLICIT partial_ordering(std::partial_ordering stdorder) noexcept
0158         : m_order{} // == equivalent
0159     {
0160         if (stdorder == std::partial_ordering::less)
0161             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
0162         else if (stdorder == std::partial_ordering::greater)
0163             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
0164         else if (stdorder == std::partial_ordering::unordered)
0165             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered);
0166     }
0167 
0168     constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
0169     {
0170         static_assert(sizeof(*this) == sizeof(std::partial_ordering));
0171 #ifdef __cpp_lib_bit_cast
0172         return std::bit_cast<std::partial_ordering>(*this);
0173 #else
0174         using O = QtPrivate::Ordering;
0175         using U = QtPrivate::Uncomparable;
0176         using R = std::partial_ordering;
0177         switch (m_order) {
0178         case qToUnderlying(O::Less):        return R::less;
0179         case qToUnderlying(O::Greater):     return R::greater;
0180         case qToUnderlying(O::Equivalent):  return R::equivalent;
0181         case qToUnderlying(U::Unordered):   return R::unordered;
0182         }
0183         Q_UNREACHABLE_RETURN(R::unordered);
0184 #endif // __cpp_lib_bit_cast
0185     }
0186 
0187     friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept
0188     { return static_cast<std::partial_ordering>(lhs) == rhs; }
0189 
0190     friend constexpr bool operator!=(partial_ordering lhs, std::partial_ordering rhs) noexcept
0191     { return static_cast<std::partial_ordering>(lhs) != rhs; }
0192 
0193     friend constexpr bool operator==(std::partial_ordering lhs, partial_ordering rhs) noexcept
0194     { return lhs == static_cast<std::partial_ordering>(rhs); }
0195 
0196     friend constexpr bool operator!=(std::partial_ordering lhs, partial_ordering rhs) noexcept
0197     { return lhs != static_cast<std::partial_ordering>(rhs); }
0198 
0199     friend constexpr bool operator==(partial_ordering lhs, std::strong_ordering rhs) noexcept
0200     { return static_cast<std::partial_ordering>(lhs) == rhs; }
0201 
0202     friend constexpr bool operator!=(partial_ordering lhs, std::strong_ordering rhs) noexcept
0203     { return static_cast<std::partial_ordering>(lhs) != rhs; }
0204 
0205     friend constexpr bool operator==(std::strong_ordering lhs, partial_ordering rhs) noexcept
0206     { return lhs == static_cast<std::partial_ordering>(rhs); }
0207 
0208     friend constexpr bool operator!=(std::strong_ordering lhs, partial_ordering rhs) noexcept
0209     { return lhs != static_cast<std::partial_ordering>(rhs); }
0210 
0211     friend constexpr bool operator==(partial_ordering lhs, std::weak_ordering rhs) noexcept
0212     { return static_cast<std::partial_ordering>(lhs) == rhs; }
0213 
0214     friend constexpr bool operator!=(partial_ordering lhs, std::weak_ordering rhs) noexcept
0215     { return static_cast<std::partial_ordering>(lhs) != rhs; }
0216 
0217     friend constexpr bool operator==(std::weak_ordering lhs, partial_ordering rhs) noexcept
0218     { return lhs == static_cast<std::partial_ordering>(rhs); }
0219 
0220     friend constexpr bool operator!=(std::weak_ordering lhs, partial_ordering rhs) noexcept
0221     { return lhs != static_cast<std::partial_ordering>(rhs); }
0222 #endif // __cpp_lib_three_way_comparison
0223 
0224 private:
0225     friend class weak_ordering;
0226     friend class strong_ordering;
0227 
0228     constexpr explicit partial_ordering(QtPrivate::Ordering order) noexcept
0229         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0230     {}
0231     constexpr explicit partial_ordering(QtPrivate::Uncomparable order) noexcept
0232         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0233     {}
0234 
0235     QT_WARNING_PUSH
0236     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
0237     QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
0238     QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant")
0239     friend constexpr bool is_eq  (partial_ordering o) noexcept { return o == 0; }
0240     friend constexpr bool is_neq (partial_ordering o) noexcept { return o != 0; }
0241     friend constexpr bool is_lt  (partial_ordering o) noexcept { return o <  0; }
0242     friend constexpr bool is_lteq(partial_ordering o) noexcept { return o <= 0; }
0243     friend constexpr bool is_gt  (partial_ordering o) noexcept { return o >  0; }
0244     friend constexpr bool is_gteq(partial_ordering o) noexcept { return o >= 0; }
0245     QT_WARNING_POP
0246 
0247     // instead of the exposition only is_ordered member in [cmp.partialord],
0248     // use a private function
0249     constexpr bool isOrdered() const noexcept
0250     { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); }
0251 
0252     QtPrivate::CompareUnderlyingType m_order;
0253 };
0254 
0255 inline constexpr partial_ordering partial_ordering::less(QtPrivate::Ordering::Less);
0256 inline constexpr partial_ordering partial_ordering::equivalent(QtPrivate::Ordering::Equivalent);
0257 inline constexpr partial_ordering partial_ordering::greater(QtPrivate::Ordering::Greater);
0258 inline constexpr partial_ordering partial_ordering::unordered(QtPrivate::Uncomparable::Unordered);
0259 
0260 class weak_ordering
0261 {
0262 public:
0263     static const weak_ordering less;
0264     static const weak_ordering equivalent;
0265     static const weak_ordering greater;
0266 
0267     constexpr Q_IMPLICIT operator partial_ordering() const noexcept
0268     { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
0269 
0270     friend constexpr bool operator==(weak_ordering lhs,
0271                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0272     { return lhs.m_order == 0; }
0273 
0274     friend constexpr bool operator!=(weak_ordering lhs,
0275                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0276     { return lhs.m_order != 0; }
0277 
0278     friend constexpr bool operator< (weak_ordering lhs,
0279                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0280     { return lhs.m_order <  0; }
0281 
0282     friend constexpr bool operator<=(weak_ordering lhs,
0283                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0284     { return lhs.m_order <= 0; }
0285 
0286     friend constexpr bool operator> (weak_ordering lhs,
0287                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0288     { return lhs.m_order >  0; }
0289 
0290     friend constexpr bool operator>=(weak_ordering lhs,
0291                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0292     { return lhs.m_order >= 0; }
0293 
0294 
0295     friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
0296                                      weak_ordering rhs) noexcept
0297     { return 0 == rhs.m_order; }
0298 
0299     friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
0300                                      weak_ordering rhs) noexcept
0301     { return 0 != rhs.m_order; }
0302 
0303     friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
0304                                      weak_ordering rhs) noexcept
0305     { return 0 <  rhs.m_order; }
0306 
0307     friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
0308                                      weak_ordering rhs) noexcept
0309     { return 0 <= rhs.m_order; }
0310 
0311     friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
0312                                      weak_ordering rhs) noexcept
0313     { return 0 > rhs.m_order; }
0314 
0315     friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
0316                                      weak_ordering rhs) noexcept
0317     { return 0 >= rhs.m_order; }
0318 
0319 
0320 #ifdef __cpp_lib_three_way_comparison
0321     friend constexpr std::weak_ordering
0322     operator<=>(weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
0323     { return lhs; } // https://eel.is/c++draft/cmp.weakord#5
0324 
0325     friend constexpr std::weak_ordering
0326     operator<=>(QtPrivate::CompareAgainstLiteralZero, weak_ordering rhs) noexcept
0327     { return QtOrderingPrivate::reversed(rhs); }
0328 #endif // __cpp_lib_three_way_comparison
0329 
0330 
0331     friend constexpr bool operator==(weak_ordering lhs, weak_ordering rhs) noexcept
0332     { return lhs.m_order == rhs.m_order; }
0333 
0334     friend constexpr bool operator!=(weak_ordering lhs, weak_ordering rhs) noexcept
0335     { return lhs.m_order != rhs.m_order; }
0336 
0337     friend constexpr bool operator==(weak_ordering lhs, partial_ordering rhs) noexcept
0338     { return static_cast<partial_ordering>(lhs) == rhs; }
0339 
0340     friend constexpr bool operator!=(weak_ordering lhs, partial_ordering rhs) noexcept
0341     { return static_cast<partial_ordering>(lhs) != rhs; }
0342 
0343     friend constexpr bool operator==(partial_ordering lhs, weak_ordering rhs) noexcept
0344     { return lhs == static_cast<partial_ordering>(rhs); }
0345 
0346     friend constexpr bool operator!=(partial_ordering lhs, weak_ordering rhs) noexcept
0347     { return lhs != static_cast<partial_ordering>(rhs); }
0348 
0349 #ifdef __cpp_lib_three_way_comparison
0350     constexpr Q_IMPLICIT weak_ordering(std::weak_ordering stdorder) noexcept
0351         : m_order{} // == equivalent
0352     {
0353         if (stdorder == std::weak_ordering::less)
0354             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
0355         else if (stdorder == std::weak_ordering::greater)
0356             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
0357     }
0358 
0359     constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept
0360     {
0361         static_assert(sizeof(*this) == sizeof(std::weak_ordering));
0362 #ifdef __cpp_lib_bit_cast
0363         return std::bit_cast<std::weak_ordering>(*this);
0364 #else
0365         using O = QtPrivate::Ordering;
0366         using R = std::weak_ordering;
0367         switch (m_order) {
0368         case qToUnderlying(O::Less):          return R::less;
0369         case qToUnderlying(O::Greater):       return R::greater;
0370         case qToUnderlying(O::Equivalent):    return R::equivalent;
0371         }
0372         Q_UNREACHABLE_RETURN(R::equivalent);
0373 #endif // __cpp_lib_bit_cast
0374     }
0375 
0376     friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept
0377     { return static_cast<std::weak_ordering>(lhs) == rhs; }
0378 
0379     friend constexpr bool operator!=(weak_ordering lhs, std::weak_ordering rhs) noexcept
0380     { return static_cast<std::weak_ordering>(lhs) != rhs; }
0381 
0382     friend constexpr bool operator==(weak_ordering lhs, std::partial_ordering rhs) noexcept
0383     { return static_cast<std::weak_ordering>(lhs) == rhs; }
0384 
0385     friend constexpr bool operator!=(weak_ordering lhs, std::partial_ordering rhs) noexcept
0386     { return static_cast<std::weak_ordering>(lhs) != rhs; }
0387 
0388     friend constexpr bool operator==(weak_ordering lhs, std::strong_ordering rhs) noexcept
0389     { return static_cast<std::weak_ordering>(lhs) == rhs; }
0390 
0391     friend constexpr bool operator!=(weak_ordering lhs, std::strong_ordering rhs) noexcept
0392     { return static_cast<std::weak_ordering>(lhs) != rhs; }
0393 
0394     friend constexpr bool operator==(std::weak_ordering lhs, weak_ordering rhs) noexcept
0395     { return lhs == static_cast<std::weak_ordering>(rhs); }
0396 
0397     friend constexpr bool operator!=(std::weak_ordering lhs, weak_ordering rhs) noexcept
0398     { return lhs != static_cast<std::weak_ordering>(rhs); }
0399 
0400     friend constexpr bool operator==(std::partial_ordering lhs, weak_ordering rhs) noexcept
0401     { return lhs == static_cast<std::weak_ordering>(rhs); }
0402 
0403     friend constexpr bool operator!=(std::partial_ordering lhs, weak_ordering rhs) noexcept
0404     { return lhs != static_cast<std::weak_ordering>(rhs); }
0405 
0406     friend constexpr bool operator==(std::strong_ordering lhs, weak_ordering rhs) noexcept
0407     { return lhs == static_cast<std::weak_ordering>(rhs); }
0408 
0409     friend constexpr bool operator!=(std::strong_ordering lhs, weak_ordering rhs) noexcept
0410     { return lhs != static_cast<std::weak_ordering>(rhs); }
0411 #endif // __cpp_lib_three_way_comparison
0412 
0413 private:
0414     friend class strong_ordering;
0415 
0416     constexpr explicit weak_ordering(QtPrivate::Ordering order) noexcept
0417         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0418     {}
0419 
0420     QT_WARNING_PUSH
0421     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
0422     QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
0423     QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant")
0424     friend constexpr bool is_eq  (weak_ordering o) noexcept { return o == 0; }
0425     friend constexpr bool is_neq (weak_ordering o) noexcept { return o != 0; }
0426     friend constexpr bool is_lt  (weak_ordering o) noexcept { return o <  0; }
0427     friend constexpr bool is_lteq(weak_ordering o) noexcept { return o <= 0; }
0428     friend constexpr bool is_gt  (weak_ordering o) noexcept { return o >  0; }
0429     friend constexpr bool is_gteq(weak_ordering o) noexcept { return o >= 0; }
0430     QT_WARNING_POP
0431 
0432     QtPrivate::CompareUnderlyingType m_order;
0433 };
0434 
0435 inline constexpr weak_ordering weak_ordering::less(QtPrivate::Ordering::Less);
0436 inline constexpr weak_ordering weak_ordering::equivalent(QtPrivate::Ordering::Equivalent);
0437 inline constexpr weak_ordering weak_ordering::greater(QtPrivate::Ordering::Greater);
0438 
0439 class strong_ordering
0440 {
0441 public:
0442     static const strong_ordering less;
0443     static const strong_ordering equivalent;
0444     static const strong_ordering equal;
0445     static const strong_ordering greater;
0446 
0447     constexpr Q_IMPLICIT operator partial_ordering() const noexcept
0448     { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
0449 
0450     constexpr Q_IMPLICIT operator weak_ordering() const noexcept
0451     { return weak_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
0452 
0453     friend constexpr bool operator==(strong_ordering lhs,
0454                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0455     { return lhs.m_order == 0; }
0456 
0457     friend constexpr bool operator!=(strong_ordering lhs,
0458                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0459     { return lhs.m_order != 0; }
0460 
0461     friend constexpr bool operator< (strong_ordering lhs,
0462                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0463     { return lhs.m_order <  0; }
0464 
0465     friend constexpr bool operator<=(strong_ordering lhs,
0466                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0467     { return lhs.m_order <= 0; }
0468 
0469     friend constexpr bool operator> (strong_ordering lhs,
0470                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0471     { return lhs.m_order >  0; }
0472 
0473     friend constexpr bool operator>=(strong_ordering lhs,
0474                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0475     { return lhs.m_order >= 0; }
0476 
0477 
0478     friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
0479                                      strong_ordering rhs) noexcept
0480     { return 0 == rhs.m_order; }
0481 
0482     friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
0483                                      strong_ordering rhs) noexcept
0484     { return 0 != rhs.m_order; }
0485 
0486     friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
0487                                     strong_ordering rhs) noexcept
0488     { return 0 <  rhs.m_order; }
0489 
0490     friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
0491                                      strong_ordering rhs) noexcept
0492     { return 0 <= rhs.m_order; }
0493 
0494     friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
0495                                     strong_ordering rhs) noexcept
0496     { return 0 >  rhs.m_order; }
0497 
0498     friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
0499                                      strong_ordering rhs) noexcept
0500     { return 0 >= rhs.m_order; }
0501 
0502 
0503 #ifdef __cpp_lib_three_way_comparison
0504     friend constexpr std::strong_ordering
0505     operator<=>(strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
0506     { return lhs; } // https://eel.is/c++draft/cmp.strongord#6
0507 
0508     friend constexpr std::strong_ordering
0509     operator<=>(QtPrivate::CompareAgainstLiteralZero, strong_ordering rhs) noexcept
0510     { return QtOrderingPrivate::reversed(rhs); }
0511 #endif // __cpp_lib_three_way_comparison
0512 
0513 
0514     friend constexpr bool operator==(strong_ordering lhs, strong_ordering rhs) noexcept
0515     { return lhs.m_order == rhs.m_order; }
0516 
0517     friend constexpr bool operator!=(strong_ordering lhs, strong_ordering rhs) noexcept
0518     { return lhs.m_order != rhs.m_order; }
0519 
0520     friend constexpr bool operator==(strong_ordering lhs, partial_ordering rhs) noexcept
0521     { return static_cast<partial_ordering>(lhs) == rhs; }
0522 
0523     friend constexpr bool operator!=(strong_ordering lhs, partial_ordering rhs) noexcept
0524     { return static_cast<partial_ordering>(lhs) == rhs; }
0525 
0526     friend constexpr bool operator==(partial_ordering lhs, strong_ordering rhs) noexcept
0527     { return lhs == static_cast<partial_ordering>(rhs); }
0528 
0529     friend constexpr bool operator!=(partial_ordering lhs, strong_ordering rhs) noexcept
0530     { return lhs != static_cast<partial_ordering>(rhs); }
0531 
0532     friend constexpr bool operator==(strong_ordering lhs, weak_ordering rhs) noexcept
0533     { return static_cast<weak_ordering>(lhs) == rhs; }
0534 
0535     friend constexpr bool operator!=(strong_ordering lhs, weak_ordering rhs) noexcept
0536     { return static_cast<weak_ordering>(lhs) == rhs; }
0537 
0538     friend constexpr bool operator==(weak_ordering lhs, strong_ordering rhs) noexcept
0539     { return lhs == static_cast<weak_ordering>(rhs); }
0540 
0541     friend constexpr bool operator!=(weak_ordering lhs, strong_ordering rhs) noexcept
0542     { return lhs != static_cast<weak_ordering>(rhs); }
0543 
0544 #ifdef __cpp_lib_three_way_comparison
0545     constexpr Q_IMPLICIT strong_ordering(std::strong_ordering stdorder) noexcept
0546         : m_order{} // == equivalent
0547     {
0548         if (stdorder == std::strong_ordering::less)
0549             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
0550         else if (stdorder == std::strong_ordering::greater)
0551             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
0552     }
0553 
0554     constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept
0555     {
0556         static_assert(sizeof(*this) == sizeof(std::strong_ordering));
0557 #ifdef __cpp_lib_bit_cast
0558         return std::bit_cast<std::strong_ordering>(*this);
0559 #else
0560         using O = QtPrivate::Ordering;
0561         using R = std::strong_ordering;
0562         switch (m_order) {
0563         case qToUnderlying(O::Less):    return R::less;
0564         case qToUnderlying(O::Greater): return R::greater;
0565         case qToUnderlying(O::Equal):   return R::equal;
0566         }
0567         Q_UNREACHABLE_RETURN(R::equal);
0568 #endif // __cpp_lib_bit_cast
0569     }
0570 
0571     friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept
0572     { return static_cast<std::strong_ordering>(lhs) == rhs; }
0573 
0574     friend constexpr bool operator!=(strong_ordering lhs, std::strong_ordering rhs) noexcept
0575     { return static_cast<std::strong_ordering>(lhs) != rhs; }
0576 
0577     friend constexpr bool operator==(strong_ordering lhs, std::partial_ordering rhs) noexcept
0578     { return static_cast<std::strong_ordering>(lhs) == rhs; }
0579 
0580     friend constexpr bool operator!=(strong_ordering lhs, std::partial_ordering rhs) noexcept
0581     { return static_cast<std::strong_ordering>(lhs) != rhs; }
0582 
0583     friend constexpr bool operator==(strong_ordering lhs, std::weak_ordering rhs) noexcept
0584     { return static_cast<std::strong_ordering>(lhs) == rhs; }
0585 
0586     friend constexpr bool operator!=(strong_ordering lhs, std::weak_ordering rhs) noexcept
0587     { return static_cast<std::strong_ordering>(lhs) != rhs; }
0588 
0589     friend constexpr bool operator==(std::strong_ordering lhs, strong_ordering rhs) noexcept
0590     { return lhs == static_cast<std::strong_ordering>(rhs); }
0591 
0592     friend constexpr bool operator!=(std::strong_ordering lhs, strong_ordering rhs) noexcept
0593     { return lhs != static_cast<std::strong_ordering>(rhs); }
0594 
0595     friend constexpr bool operator==(std::partial_ordering lhs, strong_ordering rhs) noexcept
0596     { return lhs == static_cast<std::strong_ordering>(rhs); }
0597 
0598     friend constexpr bool operator!=(std::partial_ordering lhs, strong_ordering rhs) noexcept
0599     { return lhs != static_cast<std::strong_ordering>(rhs); }
0600 
0601     friend constexpr bool operator==(std::weak_ordering lhs, strong_ordering rhs) noexcept
0602     { return lhs == static_cast<std::strong_ordering>(rhs); }
0603 
0604     friend constexpr bool operator!=(std::weak_ordering lhs, strong_ordering rhs) noexcept
0605     { return lhs != static_cast<std::strong_ordering>(rhs); }
0606 #endif // __cpp_lib_three_way_comparison
0607 
0608     private:
0609     constexpr explicit strong_ordering(QtPrivate::Ordering order) noexcept
0610         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0611     {}
0612 
0613     QT_WARNING_PUSH
0614     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
0615     QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
0616     QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant")
0617     friend constexpr bool is_eq  (strong_ordering o) noexcept { return o == 0; }
0618     friend constexpr bool is_neq (strong_ordering o) noexcept { return o != 0; }
0619     friend constexpr bool is_lt  (strong_ordering o) noexcept { return o <  0; }
0620     friend constexpr bool is_lteq(strong_ordering o) noexcept { return o <= 0; }
0621     friend constexpr bool is_gt  (strong_ordering o) noexcept { return o >  0; }
0622     friend constexpr bool is_gteq(strong_ordering o) noexcept { return o >= 0; }
0623     QT_WARNING_POP
0624 
0625     QtPrivate::CompareUnderlyingType m_order;
0626 };
0627 
0628 inline constexpr strong_ordering strong_ordering::less(QtPrivate::Ordering::Less);
0629 inline constexpr strong_ordering strong_ordering::equivalent(QtPrivate::Ordering::Equivalent);
0630 inline constexpr strong_ordering strong_ordering::equal(QtPrivate::Ordering::Equal);
0631 inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::Greater);
0632 
0633 } // namespace Qt
0634 
0635 QT_BEGIN_INCLUDE_NAMESPACE
0636 
0637 // This is intentionally included after Qt::*_ordering types and before
0638 // qCompareThreeWay. Do not change!
0639 #include <QtCore/qcomparehelpers.h>
0640 
0641 QT_END_INCLUDE_NAMESPACE
0642 
0643 #if defined(Q_QDOC)
0644 
0645 template <typename LeftType, typename RightType>
0646 auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs);
0647 
0648 #else
0649 
0650 template <typename LT, typename RT,
0651           std::enable_if_t<
0652                   std::disjunction_v<
0653                           QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<LT, RT>,
0654                           QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<RT, LT>>,
0655                   bool> = true>
0656 auto qCompareThreeWay(const LT &lhs, const RT &rhs)
0657         noexcept(QtOrderingPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>())
0658 {
0659     using Qt::compareThreeWay;
0660     if constexpr (QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay_v<LT, RT>) {
0661         return compareThreeWay(lhs, rhs);
0662     } else {
0663         const auto retval = compareThreeWay(rhs, lhs);
0664         return QtOrderingPrivate::reversed(retval);
0665     }
0666 }
0667 
0668 #endif // defined(Q_QDOC)
0669 
0670 //
0671 // Legacy QPartialOrdering
0672 //
0673 
0674 namespace QtPrivate {
0675 enum class LegacyUncomparable : CompareUnderlyingType
0676 {
0677     Unordered = QtPrivate::LegacyUncomparableValue
0678 };
0679 }
0680 
0681 // [cmp.partialord]
0682 class QPartialOrdering
0683 {
0684 public:
0685     static const QPartialOrdering Less;
0686     static const QPartialOrdering Equivalent;
0687     static const QPartialOrdering Greater;
0688     static const QPartialOrdering Unordered;
0689 
0690     static const QPartialOrdering less;
0691     static const QPartialOrdering equivalent;
0692     static const QPartialOrdering greater;
0693     static const QPartialOrdering unordered;
0694 
0695     friend constexpr bool operator==(QPartialOrdering lhs,
0696                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0697     { return lhs.isOrdered() && lhs.m_order == 0; }
0698 
0699     friend constexpr bool operator!=(QPartialOrdering lhs,
0700                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0701     { return !lhs.isOrdered() || lhs.m_order != 0; }
0702 
0703     friend constexpr bool operator< (QPartialOrdering lhs,
0704                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0705     { return lhs.isOrdered() && lhs.m_order <  0; }
0706 
0707     friend constexpr bool operator<=(QPartialOrdering lhs,
0708                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0709     { return lhs.isOrdered() && lhs.m_order <= 0; }
0710 
0711     friend constexpr bool operator> (QPartialOrdering lhs,
0712                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0713     { return lhs.isOrdered() && lhs.m_order >  0; }
0714 
0715     friend constexpr bool operator>=(QPartialOrdering lhs,
0716                                      QtPrivate::CompareAgainstLiteralZero) noexcept
0717     { return lhs.isOrdered() && lhs.m_order >= 0; }
0718 
0719 
0720     friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
0721                                      QPartialOrdering rhs) noexcept
0722     { return rhs.isOrdered() && 0 == rhs.m_order; }
0723 
0724     friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
0725                                      QPartialOrdering rhs) noexcept
0726     { return !rhs.isOrdered() || 0 != rhs.m_order; }
0727 
0728     friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
0729                                      QPartialOrdering rhs) noexcept
0730     { return rhs.isOrdered() && 0 <  rhs.m_order; }
0731 
0732     friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
0733                                      QPartialOrdering rhs) noexcept
0734     { return rhs.isOrdered() && 0 <= rhs.m_order; }
0735 
0736     friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
0737                                      QPartialOrdering rhs) noexcept
0738     { return rhs.isOrdered() && 0 >  rhs.m_order; }
0739 
0740     friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
0741                                      QPartialOrdering rhs) noexcept
0742     { return rhs.isOrdered() && 0 >= rhs.m_order; }
0743 
0744 
0745 #ifdef __cpp_lib_three_way_comparison
0746     friend constexpr std::partial_ordering
0747     operator<=>(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
0748     { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
0749 
0750     friend constexpr std::partial_ordering
0751     operator<=>(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) noexcept
0752     { return QtOrderingPrivate::reversed(rhs); }
0753 #endif // __cpp_lib_three_way_comparison
0754 
0755 
0756     friend constexpr bool operator==(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
0757     { return lhs.m_order == rhs.m_order; }
0758 
0759     friend constexpr bool operator!=(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
0760     { return lhs.m_order != rhs.m_order; }
0761 
0762     constexpr Q_IMPLICIT QPartialOrdering(Qt::partial_ordering order) noexcept
0763         : m_order{} // == equivalent
0764     {
0765         if (order == Qt::partial_ordering::less)
0766             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
0767         else if (order == Qt::partial_ordering::greater)
0768             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
0769         else if (order == Qt::partial_ordering::unordered)
0770             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
0771     }
0772 
0773     constexpr Q_IMPLICIT QPartialOrdering(Qt::weak_ordering stdorder) noexcept
0774         : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
0775 
0776     constexpr Q_IMPLICIT QPartialOrdering(Qt::strong_ordering stdorder) noexcept
0777         : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
0778 
0779     constexpr Q_IMPLICIT operator Qt::partial_ordering() const noexcept
0780     {
0781         using O = QtPrivate::Ordering;
0782         using U = QtPrivate::LegacyUncomparable;
0783         using R = Qt::partial_ordering;
0784         switch (m_order) {
0785         case qToUnderlying(O::Less):       return R::less;
0786         case qToUnderlying(O::Greater):    return R::greater;
0787         case qToUnderlying(O::Equivalent): return R::equivalent;
0788         case qToUnderlying(U::Unordered):  return R::unordered;
0789         }
0790         // GCC 8.x does not treat __builtin_unreachable() as constexpr
0791 #if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
0792         // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
0793         Q_UNREACHABLE();
0794 #endif
0795         return R::unordered;
0796     }
0797 
0798     friend constexpr bool operator==(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
0799     { Qt::partial_ordering qt = lhs; return qt == rhs; }
0800 
0801     friend constexpr bool operator!=(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
0802     { Qt::partial_ordering qt = lhs; return qt != rhs; }
0803 
0804     friend constexpr bool operator==(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
0805     { Qt::partial_ordering qt = rhs; return lhs == qt; }
0806 
0807     friend constexpr bool operator!=(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
0808     { Qt::partial_ordering qt = rhs; return lhs != qt; }
0809 
0810 #ifdef __cpp_lib_three_way_comparison
0811     constexpr Q_IMPLICIT QPartialOrdering(std::partial_ordering stdorder) noexcept
0812         : m_order{} // == equivalent
0813     {
0814         if (stdorder == std::partial_ordering::less)
0815             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
0816         else if (stdorder == std::partial_ordering::greater)
0817             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
0818         else if (stdorder == std::partial_ordering::unordered)
0819             m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
0820     }
0821 
0822     constexpr Q_IMPLICIT QPartialOrdering(std::weak_ordering stdorder) noexcept
0823         : QPartialOrdering(std::partial_ordering(stdorder)) {}
0824 
0825     constexpr Q_IMPLICIT QPartialOrdering(std::strong_ordering stdorder) noexcept
0826         : QPartialOrdering(std::partial_ordering(stdorder)) {}
0827 
0828     constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
0829     {
0830         using O = QtPrivate::Ordering;
0831         using U = QtPrivate::LegacyUncomparable;
0832         using R = std::partial_ordering;
0833         switch (m_order) {
0834         case qToUnderlying(O::Less):       return R::less;
0835         case qToUnderlying(O::Greater):    return R::greater;
0836         case qToUnderlying(O::Equivalent): return R::equivalent;
0837         case qToUnderlying(U::Unordered):  return R::unordered;
0838         }
0839         Q_UNREACHABLE_RETURN(R::unordered);
0840     }
0841 
0842     friend constexpr bool operator==(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
0843     { return static_cast<std::partial_ordering>(lhs) == rhs; }
0844 
0845     friend constexpr bool operator!=(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
0846     { return static_cast<std::partial_ordering>(lhs) != rhs; }
0847 
0848     friend constexpr bool operator==(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
0849     { return lhs == static_cast<std::partial_ordering>(rhs); }
0850 
0851     friend constexpr bool operator!=(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
0852     { return lhs != static_cast<std::partial_ordering>(rhs); }
0853 #endif // __cpp_lib_three_way_comparison
0854 
0855 private:
0856     constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept
0857         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0858     {}
0859     constexpr explicit QPartialOrdering(QtPrivate::LegacyUncomparable order) noexcept
0860         : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
0861     {}
0862 
0863     QT_WARNING_PUSH
0864     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
0865     QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
0866     QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant")
0867     friend constexpr bool is_eq  (QPartialOrdering o) noexcept { return o == 0; }
0868     friend constexpr bool is_neq (QPartialOrdering o) noexcept { return o != 0; }
0869     friend constexpr bool is_lt  (QPartialOrdering o) noexcept { return o <  0; }
0870     friend constexpr bool is_lteq(QPartialOrdering o) noexcept { return o <= 0; }
0871     friend constexpr bool is_gt  (QPartialOrdering o) noexcept { return o >  0; }
0872     friend constexpr bool is_gteq(QPartialOrdering o) noexcept { return o >= 0; }
0873     QT_WARNING_POP
0874 
0875     // instead of the exposition only is_ordered member in [cmp.partialord],
0876     // use a private function
0877     constexpr bool isOrdered() const noexcept
0878     { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); }
0879 
0880     QtPrivate::CompareUnderlyingType m_order;
0881 };
0882 
0883 inline constexpr QPartialOrdering QPartialOrdering::Less(QtPrivate::Ordering::Less);
0884 inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Ordering::Equivalent);
0885 inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater);
0886 inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::LegacyUncomparable::Unordered);
0887 
0888 inline constexpr QPartialOrdering QPartialOrdering::less(QtPrivate::Ordering::Less);
0889 inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Ordering::Equivalent);
0890 inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater);
0891 inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered);
0892 
0893 QT_END_NAMESPACE
0894 
0895 #endif // QCOMPARE_H