From 99d401220c3b200e76f00cb7457a5a3935379572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8ger=20Hanseg=C3=A5rd?= Date: Thu, 2 Jan 2025 15:31:43 +0100 Subject: [PATCH] Compare QUniqueHandles using comparesEqual and compareThreeWay This fixes an issue where comparing pointers to object is only defined if both pointers point into the same array. Task-number: QTBUG-132507 Pick-to: 6.8 Change-Id: Ib7ccb30001add38ad25b62c848a01cd53566d8bf Reviewed-by: Thiago Macieira (cherry picked from commit 5dcdeeebbc08be8845cdb5a0e586b7a864b7f16f) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/tools/quniquehandle_p.h | 34 +++++---------- .../tools/quniquehandle/tst_quniquehandle.cpp | 42 +++++++++++++++++++ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/corelib/tools/quniquehandle_p.h b/src/corelib/tools/quniquehandle_p.h index c746e51fe72..3ba557e838d 100644 --- a/src/corelib/tools/quniquehandle_p.h +++ b/src/corelib/tools/quniquehandle_p.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -198,37 +199,24 @@ public: m_handle = HandleTraits::invalidValue(); } - [[nodiscard]] friend bool operator==(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept +private: + friend bool comparesEqual(const QUniqueHandle& lhs, const QUniqueHandle& rhs) noexcept { return lhs.get() == rhs.get(); } - [[nodiscard]] friend bool operator!=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept + friend Qt::strong_ordering compareThreeWay(const QUniqueHandle& lhs, + const QUniqueHandle& rhs) noexcept { - return lhs.get() != rhs.get(); + if constexpr (std::is_pointer_v) + return qCompareThreeWay(Qt::totally_ordered_wrapper{ lhs.get() }, + Qt::totally_ordered_wrapper{ rhs.get() }); + else + return qCompareThreeWay(lhs.get(), rhs.get()); } - [[nodiscard]] friend bool operator<(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept - { - return lhs.get() < rhs.get(); - } + Q_DECLARE_STRONGLY_ORDERED(QUniqueHandle) - [[nodiscard]] friend bool operator<=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept - { - return lhs.get() <= rhs.get(); - } - - [[nodiscard]] friend bool operator>(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept - { - return lhs.get() > rhs.get(); - } - - [[nodiscard]] friend bool operator>=(const QUniqueHandle &lhs, const QUniqueHandle &rhs) noexcept - { - return lhs.get() >= rhs.get(); - } - -private: Type m_handle{ HandleTraits::invalidValue() }; }; diff --git a/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp index 448ea0964fb..a23b2132d66 100644 --- a/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp +++ b/tests/auto/corelib/tools/quniquehandle/tst_quniquehandle.cpp @@ -348,6 +348,48 @@ private slots: QCOMPARE_EQ(Handle{ }, Handle{ }); } + void comparison_behavesAsPointer_whenHandleTypeIsPointer_data() const + { + QTest::addColumn("lhs"); + QTest::addColumn("rhs"); + + QTest::addRow("lhs == rhs") << reinterpret_cast(2) << reinterpret_cast(2); + QTest::addRow("lhs < rhs") << reinterpret_cast(1) << reinterpret_cast(2); + QTest::addRow("lhs > rhs") << reinterpret_cast(2) << reinterpret_cast(1); + } + + void comparison_behavesAsPointer_whenHandleTypeIsPointer() const + { + struct IntPtrTraits + { + using Type = int*; + + static bool close(Type) + { + return true; + } + + static Type invalidValue() noexcept + { + return nullptr; + } + }; + + using Handle = QUniqueHandle; + + QFETCH(int*, lhs); + QFETCH(int*, rhs); + + QCOMPARE_EQ(Handle{ lhs } == Handle{ rhs }, lhs == rhs); + QCOMPARE_EQ(Handle{ lhs } != Handle{ rhs }, lhs != rhs); + QCOMPARE_EQ(Handle{ lhs } < Handle{ rhs }, lhs < rhs); + QCOMPARE_EQ(Handle{ lhs } <= Handle{ rhs }, lhs <= rhs); + QCOMPARE_EQ(Handle{ lhs } > Handle{ rhs }, lhs > rhs); + QCOMPARE_EQ(Handle{ lhs } >= Handle{ rhs }, lhs >= rhs); + + QCOMPARE_EQ(Handle{ }, Handle{ }); + } + void sort_sortsHandles() const { const auto resource0 = GlobalResource::open();