QVarLengthArray: rework comparison operators

Similarly to QList, provide compareThreeWay() helper for types that
implement compareThreeWay() helpers on their own.

Do not change the existing implementation of relational operators for
C++17 mode to avoid any potential regressions.

In C++20 mode, provide the new operator<=>() only for types that meet
the requirements of the std::three_way_comparable concept or provide
operator<().

[ChangeLog][QtCore][QVarLengthArray] QVarLengthArray now implements
operator<=>() in C++20 mode.

Task-number: QTBUG-120305
Change-Id: Ie76ac8b503b08f514fd353deb3de4f72e3237d19
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Ivan Solovev 2024-09-27 16:13:36 +02:00
parent 08c6cc62c7
commit 9cbfa8cb4c
3 changed files with 62 additions and 1 deletions

View File

@ -9,6 +9,7 @@
#pragma qt_sync_stop_processing
#endif
#include <QtCore/qcompare.h>
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qglobal.h>
#include <QtCore/qalgorithms.h>
@ -625,7 +626,39 @@ public:
friend inline bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
friend inline bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
friend inline auto operator<=>(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
#else
private:
template <typename U = T, qsizetype Prealloc2 = Prealloc,
Qt::if_has_qt_compare_three_way<U, U> = true>
friend auto
compareThreeWay(const QVarLengthArray &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
{
return QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
}
#if defined(__cpp_lib_three_way_comparison) && defined(__cpp_lib_concepts)
template <typename U = T>
using if_has_op_less_or_op_compare_three_way =
std::enable_if_t<
std::disjunction_v<QTypeTraits::has_operator_less_than<U>,
QTypeTraits::has_operator_compare_three_way<U>>,
bool>;
template <typename U = T, qsizetype Prealloc2 = Prealloc,
if_has_op_less_or_op_compare_three_way<U> = true>
friend auto
operator<=>(const QVarLengthArray &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
{
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end(),
QtOrderingPrivate::synthThreeWay);
}
#endif // __cpp_lib_three_way_comparison && __cpp_lib_concepts
public:
template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
QTypeTraits::compare_eq_result<U> operator==(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
{
@ -638,6 +671,7 @@ public:
return !(l == r);
}
#ifndef __cpp_lib_three_way_comparison
template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
QTypeTraits::compare_lt_result<U> operator<(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
@ -666,7 +700,8 @@ public:
{
return !(lhs < rhs);
}
#endif
#endif // __cpp_lib_three_way_comparison
#endif // Q_QDOC
private:
template <typename U, qsizetype Prealloc2>

View File

@ -876,6 +876,21 @@
of \c operator<().
*/
/*! \fn template<typename T, qsizetype Prealloc1, qsizetype Prealloc2> auto operator<=>(const QVarLengthArray<T,Prealloc1> &lhs, const QVarLengthArray<T,Prealloc2> &rhs)
\since 6.9
\relates QVarLengthArray
Compares the contents of \a lhs and \a rhs
\l {https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare_three_way}
{lexicographically}. Returns the result of the strongest applicable category
type, that is \c {decltype(lhs[0] <=> rhs[0])} if \c {operator<=>()} is
available for type \c {T}; otherwise \c {std::weak_ordering}.
\note This operator is only available in C++20 mode, and when the underlying
type \c T models the \c {std::three_way_comparable} concept
or provides \c {operator<()}.
*/
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc> &QVarLengthArray<T, Prealloc>::operator<<(const T &value)
\since 4.8

View File

@ -487,6 +487,17 @@ private Q_SLOTS:
{ comparisonTest_impl<QList<const int *>, Qt::strong_ordering>(); }
void comparisonTest_QList_LessOnly()
{ comparisonTest_impl<QList<LessOnly>, Qt::weak_ordering>(); }
void comparisonTest_QVarLengthArray_int()
{ comparisonTest_impl<QVarLengthArray<int>, Qt::strong_ordering>(); }
void comparisonTest_QVarLengthArray_float()
{ comparisonTest_impl<QVarLengthArray<float>, Qt::partial_ordering>(); }
void comparisonTest_QVarLengthArray_QDateTime()
{ comparisonTest_impl<QVarLengthArray<QDateTime>, Qt::weak_ordering>(); }
void comparisonTest_QVarLengthArray_intptr()
{ comparisonTest_impl<QVarLengthArray<const int *>, Qt::strong_ordering>(); }
void comparisonTest_QVarLengthArray_LessOnly()
{ comparisonTest_impl<QVarLengthArray<LessOnly>, Qt::weak_ordering>(); }
};
void tst_ContainerApiSymmetry::init()