Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-03 09:24:40

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