From 814dc9715b81ce2b3a9ba94688bcbd1bc3ee0871 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Wed, 29 May 2024 14:02:58 +0200 Subject: [PATCH] Update Qt::compareThreeWay(Qt::totally_ordered_wrapper) overloads to take compatible pointer types Unlike the old Qt::compareThreeWay() overload for raw pointers, the new overloads for the Qt::totally_ordered_wrapper didn't allow to compare wrappers of different (but compatible) pointer types (base vs derived). This patch fixes it. Ideally the constraints on operators in Qt::totally_ordered_wrapper should use std::common_type_t, but we hit a bug in VxWorks that prevents us from using it, so simply demand that the types are convertible pointers. For now that should be enough, considering that Qt::totally_ordered_wrapper only expects pointers as wrapped types. Found in API Review. Change-Id: I9f7184468bea3e1f2944ca5347f0b79eded2f4d3 Reviewed-by: Marc Mutz (cherry picked from commit d73bdec05101b34745156c8cd4ea571f1223ad32) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qcompare.cpp | 15 +++++-- src/corelib/global/qcomparehelpers.h | 45 ++++++++++++------- .../qcomparehelpers/tst_qcomparehelpers.cpp | 4 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/corelib/global/qcompare.cpp b/src/corelib/global/qcompare.cpp index 5a2ad0e2ee4..4df6146b103 100644 --- a/src/corelib/global/qcompare.cpp +++ b/src/corelib/global/qcompare.cpp @@ -1313,7 +1313,7 @@ CHECK(strong, equivalent); */ /*! - \fn template Qt::compareThreeWay(Qt::totally_ordered_wrapper lhs, Qt::totally_ordered_wrapper rhs) + \fn template = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper lhs, Qt::totally_ordered_wrapper rhs) \since 6.8 \relates \overload @@ -1323,12 +1323,15 @@ CHECK(strong, equivalent); \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} {strict total order over pointers} when doing the comparison. + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + Returns an instance of \l Qt::strong_ordering that represents the relation between \a lhs and \a rhs. */ /*! - \fn template Qt::compareThreeWay(Qt::totally_ordered_wrapper lhs, T *rhs) + \fn template = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper lhs, U *rhs) \since 6.8 \relates \overload @@ -1338,12 +1341,15 @@ CHECK(strong, equivalent); \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} {strict total order over pointers} when doing the comparison. + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + Returns an instance of \l Qt::strong_ordering that represents the relation between \a lhs and \a rhs. */ /*! - \fn template Qt::compareThreeWay(T *lhs, Qt::totally_ordered_wrapper rhs) + \fn template = true> Qt::compareThreeWay(U *lhs, Qt::totally_ordered_wrapper rhs) \since 6.8 \relates \overload @@ -1353,6 +1359,9 @@ CHECK(strong, equivalent); \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} {strict total order over pointers} when doing the comparison. + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + Returns an instance of \l Qt::strong_ordering that represents the relation between \a lhs and \a rhs. */ diff --git a/src/corelib/global/qcomparehelpers.h b/src/corelib/global/qcomparehelpers.h index 48a440274b8..02aa9d9283a 100644 --- a/src/corelib/global/qcomparehelpers.h +++ b/src/corelib/global/qcomparehelpers.h @@ -657,24 +657,37 @@ public: explicit constexpr operator bool() const noexcept { return get(); } private: + // TODO: Replace the constraints with std::common_type_t when + // a bug in VxWorks is fixed! + template + using if_compatible_types = + std::enable_if_t, + std::is_pointer, + std::disjunction, + std::is_convertible>>, + bool>; + #define MAKE_RELOP(Ret, op, Op) \ - friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, const totally_ordered_wrapper &rhs) noexcept \ - { return std:: Op {}(lhs.ptr, rhs.ptr); } \ - friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, const P &rhs) noexcept \ + template = true> \ + friend constexpr Ret operator op (const totally_ordered_wrapper

&lhs, const totally_ordered_wrapper &rhs) noexcept \ + { return std:: Op {}(lhs.ptr, rhs.get()); } \ + template = true> \ + friend constexpr Ret operator op (const totally_ordered_wrapper

&lhs, const U &rhs) noexcept \ { return std:: Op {}(lhs.ptr, rhs ); } \ - friend constexpr Ret operator op (const P &lhs, const totally_ordered_wrapper &rhs) noexcept \ + template = true> \ + friend constexpr Ret operator op (const U &lhs, const totally_ordered_wrapper

&rhs) noexcept \ { return std:: Op {}(lhs, rhs.ptr); } \ friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, std::nullptr_t) noexcept \ { return std:: Op {}(lhs.ptr, P(nullptr)); } \ friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \ { return std:: Op {}(P(nullptr), rhs.ptr); } \ /* end */ - MAKE_RELOP(bool, ==, equal_to

) - MAKE_RELOP(bool, !=, not_equal_to

) - MAKE_RELOP(bool, < , less

) - MAKE_RELOP(bool, <=, less_equal

) - MAKE_RELOP(bool, > , greater

) - MAKE_RELOP(bool, >=, greater_equal

) + MAKE_RELOP(bool, ==, equal_to<>) + MAKE_RELOP(bool, !=, not_equal_to<>) + MAKE_RELOP(bool, < , less<>) + MAKE_RELOP(bool, <=, less_equal<>) + MAKE_RELOP(bool, > , greater<>) + MAKE_RELOP(bool, >=, greater_equal<>) #ifdef __cpp_lib_three_way_comparison MAKE_RELOP(auto, <=>, compare_three_way) #endif @@ -687,23 +700,23 @@ private: { return qHash(key.ptr, seed); } }; -template +template = true> constexpr Qt::strong_ordering -compareThreeWay(Qt::totally_ordered_wrapper lhs, Qt::totally_ordered_wrapper rhs) noexcept +compareThreeWay(Qt::totally_ordered_wrapper lhs, Qt::totally_ordered_wrapper rhs) noexcept { return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); } -template +template = true> constexpr Qt::strong_ordering -compareThreeWay(Qt::totally_ordered_wrapper lhs, T *rhs) noexcept +compareThreeWay(Qt::totally_ordered_wrapper lhs, U *rhs) noexcept { return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); } -template +template = true> constexpr Qt::strong_ordering -compareThreeWay(T *lhs, Qt::totally_ordered_wrapper rhs) noexcept +compareThreeWay(U *lhs, Qt::totally_ordered_wrapper rhs) noexcept { return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); } diff --git a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp index 3a910e1839b..69571c9b234 100644 --- a/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp +++ b/tests/auto/corelib/global/qcomparehelpers/tst_qcomparehelpers.cpp @@ -610,8 +610,10 @@ QT_WARNING_POP QCOMPARE_EQ(Qt::compareThreeWay(arr.data(), a0), Qt::strong_ordering::equivalent); auto bWrapper = Qt::totally_ordered_wrapper(b.get()); - auto dWrapper = Qt::totally_ordered_wrapper(d.get()); + auto dWrapper = Qt::totally_ordered_wrapper(d.get()); QCOMPARE_NE(Qt::compareThreeWay(bWrapper, dWrapper), Qt::strong_ordering::equivalent); + QCOMPARE_NE(Qt::compareThreeWay(bWrapper, d.get()), Qt::strong_ordering::equivalent); + QCOMPARE_NE(Qt::compareThreeWay(b.get(), dWrapper), Qt::strong_ordering::equivalent); QCOMPARE_EQ(Qt::compareThreeWay(bWrapper, nullptr), Qt::strong_ordering::greater); QCOMPARE_EQ(Qt::compareThreeWay(nullptr, dWrapper), Qt::strong_ordering::less);