From 9cbfa8cb4c68ffa9b0d60ef1f0944ae3dab809d8 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Fri, 27 Sep 2024 16:13:36 +0200 Subject: [PATCH] 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 --- src/corelib/tools/qvarlengtharray.h | 37 ++++++++++++++++++- src/corelib/tools/qvarlengtharray.qdoc | 15 ++++++++ .../tst_containerapisymmetry.cpp | 11 ++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 66c8e0bd134..fb3c53c49cd 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -9,6 +9,7 @@ #pragma qt_sync_stop_processing #endif +#include #include #include #include @@ -625,7 +626,39 @@ public: friend inline bool operator<=(const QVarLengthArray &l, const QVarLengthArray &r); template friend inline bool operator>=(const QVarLengthArray &l, const QVarLengthArray &r); + template + friend inline auto operator<=>(const QVarLengthArray &l, const QVarLengthArray &r); #else +private: + template = true> + friend auto + compareThreeWay(const QVarLengthArray &lhs, const QVarLengthArray &rhs) + { + return QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); + } + +#if defined(__cpp_lib_three_way_comparison) && defined(__cpp_lib_concepts) + template + using if_has_op_less_or_op_compare_three_way = + std::enable_if_t< + std::disjunction_v, + QTypeTraits::has_operator_compare_three_way>, + bool>; + + template = true> + friend auto + operator<=>(const QVarLengthArray &lhs, const QVarLengthArray &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 friend QTypeTraits::compare_eq_result operator==(const QVarLengthArray &l, const QVarLengthArray &r) { @@ -638,6 +671,7 @@ public: return !(l == r); } +#ifndef __cpp_lib_three_way_comparison template friend QTypeTraits::compare_lt_result operator<(const QVarLengthArray &lhs, const QVarLengthArray &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 diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index 0715f519448..85d957b5bb7 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -876,6 +876,21 @@ of \c operator<(). */ +/*! \fn template auto operator<=>(const QVarLengthArray &lhs, const QVarLengthArray &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 QVarLengthArray &QVarLengthArray::operator<<(const T &value) \since 4.8 diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index f8115305b84..86d9904d91b 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -487,6 +487,17 @@ private Q_SLOTS: { comparisonTest_impl, Qt::strong_ordering>(); } void comparisonTest_QList_LessOnly() { comparisonTest_impl, Qt::weak_ordering>(); } + + void comparisonTest_QVarLengthArray_int() + { comparisonTest_impl, Qt::strong_ordering>(); } + void comparisonTest_QVarLengthArray_float() + { comparisonTest_impl, Qt::partial_ordering>(); } + void comparisonTest_QVarLengthArray_QDateTime() + { comparisonTest_impl, Qt::weak_ordering>(); } + void comparisonTest_QVarLengthArray_intptr() + { comparisonTest_impl, Qt::strong_ordering>(); } + void comparisonTest_QVarLengthArray_LessOnly() + { comparisonTest_impl, Qt::weak_ordering>(); } }; void tst_ContainerApiSymmetry::init()