From eae3d0807a0a3302db87311737acf6dc6829cb69 Mon Sep 17 00:00:00 2001 From: Tatiana Borisova Date: Mon, 5 Aug 2024 19:01:34 +0200 Subject: [PATCH] Convert a Qt ordering type to the weaker std ordering type - Added missing conversion from Qt::strong_ordering to std::weak_ordering, std::partial_ordering. - Added missing conversion from Qt::weak_ordering to std::partial_ordering. Usage of Q_IMPLICIT specifier in new std::*_ordering conversion functions leads to following ambiguity errors on WIN + MSVC configuration: C:/Users/qt/work/qt/qtbase/src/corelib/global/qcompare.h(334): error C2440: 'static_cast': cannot convert from 'Qt::weak_ordering' to 'Qt::partial_ordering' qcompare.h(334): note: 'Qt::partial_ordering::partial_ordering': ambiguous call to overloaded function qcompare.h(249): note: could be 'Qt::partial_ordering::partial_ordering(Qt::partial_ordering &&)' qcompare.h(153): note: or 'Qt::partial_ordering::partial_ordering(std::partial_ordering) noexcept' qcompare.h(334): note: while trying to match the argument list '(Qt::weak_ordering)' For solving the problem we can exclude the conversion function from the argument list(make it explicit in case of MSVC). Q_COMPARE_CAST_IMPLICIT is used for setting explicit or implicit specifier depending on the compiler type [ChangeLog][QtCore][QtCompare] Added missing conversions from Qt ordering types to std ordering types. Fixes: QTBUG-127670 Pick-to: 6.7 Change-Id: I32a9a33fa8921c75b0e5a40bd413572f1bd6765a Reviewed-by: Ivan Solovev Reviewed-by: Thiago Macieira (cherry picked from commit 521e091bca1764d53ac06bb60707475d1032f5d5) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qcompare.h | 59 +++++++++++++++++++ .../corelib/global/qcompare/tst_qcompare.cpp | 14 +++++ 2 files changed, 73 insertions(+) diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h index fd9fb84c6b9..ba6b5afcd0e 100644 --- a/src/corelib/global/qcompare.h +++ b/src/corelib/global/qcompare.h @@ -21,6 +21,12 @@ QT_BEGIN_NAMESPACE +#if defined(Q_CC_MSVC) +#define Q_COMPARE_CAST_IMPLICIT explicit +#else +#define Q_COMPARE_CAST_IMPLICIT Q_IMPLICIT +#endif // Q_CC_MSVC + namespace QtPrivate { using CompareUnderlyingType = qint8; @@ -361,6 +367,23 @@ public: #endif // __cpp_lib_bit_cast } + constexpr Q_COMPARE_CAST_IMPLICIT operator std::partial_ordering() const noexcept + { + static_assert(sizeof(*this) == sizeof(std::partial_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else + using O = QtPrivate::Ordering; + using R = std::partial_ordering; + switch (m_order) { + case qToUnderlying(O::Less): return R::less; + case qToUnderlying(O::Greater): return R::greater; + case qToUnderlying(O::Equivalent): return R::equivalent; + } + Q_UNREACHABLE_RETURN(R::unordered); +#endif // __cpp_lib_bit_cast + } + friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept { return static_cast(lhs) == rhs; } @@ -558,6 +581,40 @@ public: #endif // __cpp_lib_bit_cast } + constexpr Q_COMPARE_CAST_IMPLICIT operator std::weak_ordering() const noexcept + { + static_assert(sizeof(*this) == sizeof(std::weak_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else + using O = QtPrivate::Ordering; + using R = std::weak_ordering; + switch (m_order) { + case qToUnderlying(O::Less): return R::less; + case qToUnderlying(O::Greater): return R::greater; + case qToUnderlying(O::Equal): return R::equivalent; + } + Q_UNREACHABLE_RETURN(R::equivalent); +#endif // __cpp_lib_bit_cast + } + + constexpr Q_COMPARE_CAST_IMPLICIT operator std::partial_ordering() const noexcept + { + static_assert(sizeof(*this) == sizeof(std::partial_ordering)); +#ifdef __cpp_lib_bit_cast + return std::bit_cast(*this); +#else + using O = QtPrivate::Ordering; + using R = std::partial_ordering; + switch (m_order) { + case qToUnderlying(O::Less): return R::less; + case qToUnderlying(O::Greater): return R::greater; + case qToUnderlying(O::Equal): return R::equivalent; + } + Q_UNREACHABLE_RETURN(R::unordered); +#endif // __cpp_lib_bit_cast + } + friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept { return static_cast(lhs) == rhs; } @@ -913,6 +970,8 @@ inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Orderi inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater); inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered); +#undef Q_COMPARE_CAST_IMPLICIT + QT_END_NAMESPACE #endif // QCOMPARE_H diff --git a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp index 8d764ad5257..30edd5f7345 100644 --- a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp +++ b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp @@ -693,6 +693,20 @@ void tst_QCompare::conversions() static_assert(Qt::partial_ordering::less == std::weak_ordering::less); static_assert(Qt::partial_ordering::equivalent == std::strong_ordering::equivalent); static_assert(Qt::partial_ordering::equivalent != std::strong_ordering::less); + + // convert Qt::strong to std::partial + constexpr Qt::strong_ordering qtS = Qt::strong_ordering::less; + constexpr std::partial_ordering stdP1 = qtS; + static_assert(stdP1 == qtS); + + // convert Qt::strong to std::weak + constexpr std::weak_ordering stdW = qtS; + static_assert(stdW == qtS); + + // convert Qt::weak to std::partial + constexpr Qt::weak_ordering qtW = Qt::weak_ordering::greater; + constexpr std::partial_ordering stdP2 = qtW; + static_assert(stdP2 == qtW); } #endif