Add Qt::compareThreeWay() overloads for Qt::totally_ordered_wrapper

Provide the overloads as free functions in Qt namespace instead of
making them hidden friends of the Qt::totally_ordered_wrapper class,
because they should replace the to-be-deprecated overloads of
Qt::compareThreeWay() for raw pointers, so they should be
easily discoverable.
Also, we treat Qt::compareThreeWay() as a C++17 equivalent of
operator<=>(), so we need to have an overload for pointers (even
if it takes only the wrapped pointers).

Found in API Review.

[ChangeLog][QtCore][QtCompare] Added Qt::compareThreeWay() overloads
for Qt::totally_ordered_wrapper. These overloads do the comparison
using strict total ordering.

Change-Id: I2b5bc542c546330ca78c6284188c8167136a849e
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit d6e1df3513c7d5b6e93d68583fc4c1febb7bcd85)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2024-05-23 14:03:59 +02:00 committed by Qt Cherry-pick Bot
parent 8e61693bea
commit e24f931b9f
3 changed files with 140 additions and 4 deletions

View File

@ -1308,6 +1308,77 @@ CHECK(strong, equivalent);
between \a lhs and \a rhs.
*/
/*!
\fn template <typename T> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<T*> rhs)
\since 6.8
\relates <QtCompare>
\overload
Implements three-way comparison of pointers that are wrapped into
\l Qt::totally_ordered_wrapper. Uses
\l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order}
{strict total order over pointers} when doing the comparison.
Returns an instance of \l Qt::strong_ordering that represents the relation
between \a lhs and \a rhs.
*/
/*!
\fn template <typename T> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, T *rhs)
\since 6.8
\relates <QtCompare>
\overload
Implements three-way comparison of a pointer wrapped into
\l Qt::totally_ordered_wrapper with a normal pointer. Uses
\l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order}
{strict total order over pointers} when doing the comparison.
Returns an instance of \l Qt::strong_ordering that represents the relation
between \a lhs and \a rhs.
*/
/*!
\fn template <typename T> Qt::compareThreeWay(T *lhs, Qt::totally_ordered_wrapper<T*> rhs)
\since 6.8
\relates <QtCompare>
\overload
Implements three-way comparison of a normal pointer with a pointer wrapped
into \l Qt::totally_ordered_wrapper. Uses
\l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order}
{strict total order over pointers} when doing the comparison.
Returns an instance of \l Qt::strong_ordering that represents the relation
between \a lhs and \a rhs.
*/
/*!
\fn template <typename T> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs)
\since 6.8
\relates <QtCompare>
\overload
Implements three-way comparison of a pointer wrapped into
\l Qt::totally_ordered_wrapper with \c {std::nullptr_t}.
Returns an instance of \l Qt::strong_ordering that represents the relation
between \a lhs and \a rhs.
*/
/*!
\fn template <typename T> Qt::compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs)
\since 6.8
\relates <QtCompare>
\overload
Implements three-way comparison of \c {std::nullptr_t} with a pointer
wrapped into \l Qt::totally_ordered_wrapper.
Returns an instance of \l Qt::strong_ordering that represents the relation
between \a lhs and \a rhs.
*/
/*!
\fn template <typename LeftType, typename RightType> qCompareThreeWay(const LeftType &lhs, const RightType &rhs)
\since 6.7

View File

@ -451,6 +451,26 @@ constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true;
} // namespace QtPrivate
namespace QtOrderingPrivate {
template <typename T, typename U>
constexpr Qt::strong_ordering
strongOrderingCompareDefaultImpl(T lhs, U rhs) noexcept
{
#ifdef __cpp_lib_three_way_comparison
return lhs <=> rhs;
#else
if (lhs == rhs)
return Qt::strong_ordering::equivalent;
else if (lhs < rhs)
return Qt::strong_ordering::less;
else
return Qt::strong_ordering::greater;
#endif // __cpp_lib_three_way_comparison
}
} // namespace QtOrderingPrivate
namespace Qt {
template <typename T>
@ -630,8 +650,6 @@ public:
explicit constexpr operator bool() const noexcept { return get(); }
private:
friend constexpr auto compareThreeWay(const totally_ordered_wrapper &lhs, const totally_ordered_wrapper &rhs) noexcept
{ return Qt::compareThreeWay(lhs.ptr, rhs.ptr); }
#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); } \
@ -640,9 +658,9 @@ private:
friend constexpr Ret operator op (const P &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, nullptr); } \
{ return std:: Op {}(lhs.ptr, P(nullptr)); } \
friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \
{ return std:: Op {}(nullptr, rhs.ptr); } \
{ return std:: Op {}(P(nullptr), rhs.ptr); } \
/* end */
MAKE_RELOP(bool, ==, equal_to<P>)
MAKE_RELOP(bool, !=, not_equal_to<P>)
@ -662,6 +680,41 @@ private:
{ return qHash(key.ptr, seed); }
};
template <typename T>
constexpr Qt::strong_ordering
compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept
{
return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
}
template <typename T>
constexpr Qt::strong_ordering
compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, T *rhs) noexcept
{
return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
}
template <typename T>
constexpr Qt::strong_ordering
compareThreeWay(T *lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept
{
return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
}
template <typename T>
constexpr Qt::strong_ordering
compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) noexcept
{
return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
}
template <typename T>
constexpr Qt::strong_ordering
compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept
{
return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs);
}
} //Qt
template <typename P>

View File

@ -593,6 +593,18 @@ void tst_QCompareHelpers::builtinOrder()
QCOMPARE_EQ(Qt::compareThreeWay(b.get(), nullptr), Qt::strong_ordering::greater);
QCOMPARE_EQ(Qt::compareThreeWay(nullptr, d.get()), Qt::strong_ordering::less);
// Check Qt::totally_ordered_wrapper
auto a0 = Qt::totally_ordered_wrapper(&arr[0]);
auto a1 = Qt::totally_ordered_wrapper(&arr[1]);
QCOMPARE_EQ(Qt::compareThreeWay(a0, a1), Qt::strong_ordering::less);
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<Base*>(d.get());
QCOMPARE_NE(Qt::compareThreeWay(bWrapper, 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);
#undef TEST_BUILTIN
}