Add QtOrderingPrivate::lexicographicalCompareThreeWay

This function should behave similarly to
std::lexicographical_compare_three_way, but be available in C++17.
It is required at least to properly implement the
compareThreeWay() helper function for Qt container types.

The function requires that the contained types of the compared
ranges provide a compareThreeWay() helper function.

Similarly to std implementation, this patch also adds an overload
that takes a custom comparator object.

For now the functions are added in a private namespace, because
they are only required to implement relational operators on Qt
containers. We might want to expose them as public API later, if
needed.

Task-number: QTBUG-127095
Task-number: QTBUG-120305
Change-Id: I5b29129905b2e801ae7e470c96a7ef71e7b210d6
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Ivan Solovev 2024-08-01 19:41:39 +02:00
parent fc947593ef
commit 2f8f274cae
4 changed files with 566 additions and 0 deletions

View File

@ -1563,6 +1563,42 @@ CHECK(strong, equivalent);
\sa Qt::partial_ordering, Qt::weak_ordering, Qt::strong_ordering
*/
/*!
\fn template <typename InputIt1, typename InputIt2> QtOrderingPrivate::lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
\internal
\relates <QtCompare>
\brief Three-way lexicographic comparison of ranges.
Checks how the range [ \a first1, \a last1 ) compares to the second range
[ \a first2, \a last2 ) and produces a result of the strongest applicable
category type.
This function can only be used if \c InputIt1::value_type and
\c InputIt2::value_type types provide a \c {compareThreeWay()} helper method
that returns one of the Qt ordering types.
\sa {Comparison types overview}
*/
/*!
\fn template <typename InputIt1, typename InputIt2, typename Comparator> QtOrderingPrivate::lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Comparator cmp)
\internal
\relates <QtCompare>
\overload
This overload takes a custom \c Comparator that is used to do the comparison.
The comparator should have the following signature:
\badcode
OrderingType cmp(const InputIt1::value_type &lhs, const InputIt2::value_type &rhs);
\endcode
where \c OrderingType is one of the Qt ordering types.
\sa {Comparison types overview}
*/
/*!
\class Qt::totally_ordered_wrapper
\inmodule QtCore

View File

@ -1195,6 +1195,9 @@ namespace CompareThreeWayTester {
using Qt::compareThreeWay;
template <typename T>
using WrappedType = std::conditional_t<std::is_pointer_v<T>, Qt::totally_ordered_wrapper<T>, T>;
// Check if compareThreeWay is implemented for the (LT, RT) argument
// pair.
template <typename LT, typename RT, typename = void>
@ -1205,6 +1208,13 @@ constexpr inline bool hasCompareThreeWay<
LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))>
> = true;
template <typename LT, typename RT>
constexpr inline bool hasCompareThreeWay<
LT*, RT*,
std::void_t<decltype(compareThreeWay(std::declval<WrappedType<LT>>(),
std::declval<WrappedType<RT>>()))>
> = true;
// Check if the operation is noexcept. We have two different overloads,
// depending on the available compareThreeWay() implementation.
// Both are declared, but not implemented. To be used only in unevaluated
@ -1223,8 +1233,86 @@ constexpr bool compareThreeWayNoexcept() noexcept
} // namespace CompareThreeWayTester
// These checks do not use Qt::compareThreeWay(), so only work for user-defined
// compareThreeWay() helper functions.
// We cannot use the same condition as in CompareThreeWayTester::hasCompareThreeWay,
// because GCC seems to cache and re-use the result.
// Created https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117174
// For now, modify the condition a bit without changing its meaning.
template <typename LT, typename RT = LT, typename = void>
struct HasCustomCompareThreeWay : std::false_type {};
template <typename LT, typename RT>
struct HasCustomCompareThreeWay<
LT, RT,
std::void_t<decltype(is_eq(compareThreeWay(std::declval<LT>(), std::declval<RT>())))>
> : std::true_type {};
template <typename InputIt1, typename InputIt2, typename Compare>
auto lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
Compare cmp)
{
using R = decltype(cmp(*first1, *first2));
while (first1 != last1) {
if (first2 == last2)
return R::greater;
const auto r = cmp(*first1, *first2);
if (is_neq(r))
return r;
++first1;
++first2;
}
return first2 == last2 ? R::equivalent : R::less;
}
template <typename InputIt1, typename InputIt2>
auto lexicographicalCompareThreeWay(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2)
{
using LT = typename std::iterator_traits<InputIt1>::value_type;
using RT = typename std::iterator_traits<InputIt2>::value_type;
// if LT && RT are pointers, and there is no user-defined compareThreeWay()
// operation for the pointers, we need to wrap them into
// Qt::totally_ordered_wrapper.
constexpr bool UseWrapper =
std::conjunction_v<std::is_pointer<LT>, std::is_pointer<RT>,
std::negation<HasCustomCompareThreeWay<LT, RT>>,
std::negation<HasCustomCompareThreeWay<RT, LT>>>;
using WrapLT = std::conditional_t<UseWrapper,
Qt::totally_ordered_wrapper<LT>,
const LT &>;
using WrapRT = std::conditional_t<UseWrapper,
Qt::totally_ordered_wrapper<RT>,
const RT &>;
auto cmp = [](LT const &lhs, RT const &rhs) {
using Qt::compareThreeWay;
namespace Test = QtOrderingPrivate::CompareThreeWayTester;
// Need this because the user might provide only
// compareThreeWay(LT, RT), but not the reversed version.
if constexpr (Test::hasCompareThreeWay<WrapLT, WrapRT>)
return compareThreeWay(WrapLT(lhs), WrapRT(rhs));
else
return QtOrderingPrivate::reversed(compareThreeWay(WrapRT(rhs), WrapLT(lhs)));
};
return lexicographicalCompareThreeWay(first1, last1, first2, last2, cmp);
}
} // namespace QtOrderingPrivate
namespace Qt {
template <typename T, typename U>
using if_has_qt_compare_three_way =
std::enable_if_t<QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<T, U>
|| QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay<U, T>,
bool>;
} // namespace Qt
QT_END_NAMESPACE
namespace std {

View File

@ -66,6 +66,42 @@ private Q_SLOTS:
void totallyOrderedWrapperBasics();
void compareAutoReturnType();
private:
template <typename LeftType, typename RightType, typename OrderingType>
void lexicographicalCompareThreeWayDataImpl();
template <typename LeftType, typename RightType, typename OrderingType>
void lexicographicalCompareThreeWayImpl();
template <typename LeftType, typename RightType, typename OrderingType>
void lexicographicalCompareThreeWayComparatorImpl();
private slots:
void lexicographicalCompareThreeWay_ThreeWayCmp_Int_data();
void lexicographicalCompareThreeWay_ThreeWayCmp_Int();
void lexicographicalCompareThreeWay_ThreeWayCmp_Float_data();
void lexicographicalCompareThreeWay_ThreeWayCmp_Float();
void lexicographicalCompareThreeWay_ThreeWayCmp_Weak_data();
void lexicographicalCompareThreeWay_ThreeWayCmp_Weak();
void lexicographicalCompareThreeWay_Mixed_Int_data();
void lexicographicalCompareThreeWay_Mixed_Int();
void lexicographicalCompareThreeWay_Mixed_Float_data();
void lexicographicalCompareThreeWay_Mixed_Float();
void lexicographicalCompareThreeWay_Mixed_Weak_data();
void lexicographicalCompareThreeWay_Mixed_Weak();
void lexicographicalCompareThreeWay_Comparator_Int_data();
void lexicographicalCompareThreeWay_Comparator_Int();
void lexicographicalCompareThreeWay_Comparator_Float_data();
void lexicographicalCompareThreeWay_Comparator_Float();
void lexicographicalCompareThreeWay_Comparator_Weak_data();
void lexicographicalCompareThreeWay_Comparator_Weak();
void lexicographicalCompareThreeWay_Pointers();
void lexicographicalCompareThreeWay_NonCopyMove();
void lexicographicalCompareThreeWay_CustomPointerHelper();
};
#endif // TST_QCOMPAREHELPERS_H

View File

@ -198,3 +198,409 @@ void tst_QCompareHelpers::compareAutoReturnType()
QTestPrivate::testAllComparisonOperatorsCompile<WeakT>();
}
}
template <typename T>
class LessOnly
{
public:
using Type = T;
LessOnly(T v) : val(v) {}
T value() const { return val; }
private:
friend bool operator<(LessOnly lhs, LessOnly rhs)
{ return lhs.val < rhs.val; }
T val;
};
template <typename T>
class ThreeWayCmp
{
public:
using Type = T;
ThreeWayCmp(T v) : val(v) {}
private:
template <typename U = T>
friend bool operator==(ThreeWayCmp lhs, ThreeWayCmp rhs)
{ return lhs.val == rhs.val; }
template <typename U = T>
friend bool operator==(ThreeWayCmp lhs, LessOnly<U> rhs)
{ return lhs.val == rhs.value(); }
template <typename U = T>
friend auto compareThreeWay(ThreeWayCmp lhs, ThreeWayCmp rhs)
{
using Qt::compareThreeWay;
return compareThreeWay(lhs.val, rhs.val);
}
template <typename U = T>
friend auto compareThreeWay(ThreeWayCmp lhs, LessOnly<U> rhs)
{
using Qt::compareThreeWay;
return compareThreeWay(lhs.val, rhs.value());
}
T val;
};
// A dummy int-based class to implement weak ordering
struct Weak
{
int val;
private:
friend constexpr bool comparesEqual(Weak lhs, Weak rhs) noexcept
{ return lhs.val == rhs.val; }
friend constexpr Qt::weak_ordering compareThreeWay(Weak lhs, Weak rhs) noexcept
{
const auto r = Qt::compareThreeWay(lhs.val, rhs.val);
return Qt::weak_ordering{r};
}
Q_DECLARE_WEAKLY_ORDERED_LITERAL_TYPE(Weak)
};
template <typename LeftType, typename RightType, typename OrderingType>
void tst_QCompareHelpers::lexicographicalCompareThreeWayDataImpl()
{
QTest::addColumn<QList<LeftType>>("lhs");
QTest::addColumn<QList<RightType>>("rhs");
QTest::addColumn<OrderingType>("expectedResult");
using LT = typename LeftType::Type;
using RT = typename RightType::Type;
constexpr bool HasOnlyOpLess = std::is_same_v<LeftType, LessOnly<LT>>
&& std::is_same_v<RightType, LessOnly<RT>>;
if constexpr (!HasOnlyOpLess)
static_assert(std::is_same_v<Qt::if_has_qt_compare_three_way<LeftType, RightType>, bool>);
QTest::addRow("empty")
<< QList<LeftType>{}
<< QList<RightType>{}
<< OrderingType::equivalent;
QTest::addRow("same_length_equal")
<< QList<LeftType>{LT{1}, LT{2}, LT{3}}
<< QList<RightType>{RT{1}, RT{2}, RT{3}}
<< OrderingType::equivalent;
QTest::addRow("greater_val")
<< QList<LeftType>{LT{1}, LT{3}, LT{2}}
<< QList<RightType>{RT{1}, RT{2}, RT{3}, RT{4}}
<< OrderingType::greater;
QTest::addRow("less_val")
<< QList<LeftType>{LT{1}, LT{2}, LT{3}, LT{4}}
<< QList<RightType>{RT{1}, RT{3}, RT{2}}
<< OrderingType::less;
QTest::addRow("greater_length")
<< QList<LeftType>{LT{1}, LT{2}, LT{3}}
<< QList<RightType>{RT{1}, RT{2}}
<< OrderingType::greater;
QTest::addRow("less_length")
<< QList<LeftType>{LT{1}, LT{2}, LT{3}}
<< QList<RightType>{RT{1}, RT{2}, RT{3}, RT{4}}
<< OrderingType::less;
if constexpr (!HasOnlyOpLess && std::is_same_v<OrderingType, Qt::partial_ordering>) {
const float nan = std::numeric_limits<float>::quiet_NaN();
QTest::addRow("unordered")
<< QList<LeftType>{LT{nan}, LT{2}, LT{3}}
<< QList<RightType>{RT{1}, RT{2}, RT{3}}
<< OrderingType::unordered;
QTest::addRow("unordered_start_with_nan")
<< QList<LeftType>{LT{nan}, LT{2}, LT{3}}
<< QList<RightType>{RT{nan}, RT{3}, RT{2}}
<< OrderingType::unordered;
}
}
template <typename LeftType, typename RightType, typename OrderingType>
void tst_QCompareHelpers::lexicographicalCompareThreeWayImpl()
{
QFETCH(const QList<LeftType>, lhs);
QFETCH(const QList<RightType>, rhs);
QFETCH(const OrderingType, expectedResult);
const auto res =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
QCOMPARE_EQ(res, expectedResult);
// check the C-style arrays as well
const auto rawRes =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.data(), lhs.data() + lhs.size(),
rhs.data(), rhs.data() + rhs.size());
QCOMPARE_EQ(rawRes, expectedResult);
}
template <typename LT, typename RT = LT>
Qt::strong_ordering lessOnlyCmp(LT const &lhs, RT const &rhs)
{
if (std::less<>{}(lhs, rhs))
return Qt::strong_ordering::less;
if (std::less<>{}(rhs, lhs))
return Qt::strong_ordering::greater;
return Qt::strong_ordering::equivalent;
}
template <typename LeftType, typename RightType, typename OrderingType>
void tst_QCompareHelpers::lexicographicalCompareThreeWayComparatorImpl()
{
QFETCH(const QList<LeftType>, lhs);
QFETCH(const QList<RightType>, rhs);
QFETCH(const OrderingType, expectedResult);
// free function
{
const auto res =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end(),
lessOnlyCmp<LeftType, RightType>);
QCOMPARE_EQ(res, expectedResult);
// check the C-style arrays as well
const auto rawRes =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.data(), lhs.data() + lhs.size(),
rhs.data(), rhs.data() + rhs.size(),
lessOnlyCmp<LeftType, RightType>);
QCOMPARE_EQ(rawRes, expectedResult);
}
// lambda
{
auto cmp = [](LeftType const &lhs, RightType const &rhs) {
return lessOnlyCmp(lhs, rhs);
};
const auto res =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end(),
cmp);
QCOMPARE_EQ(res, expectedResult);
// check the C-style arrays as well
const auto rawRes =
QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.data(), lhs.data() + lhs.size(),
rhs.data(), rhs.data() + rhs.size(),
std::move(cmp));
QCOMPARE_EQ(rawRes, expectedResult);
}
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Int_data()
{
lexicographicalCompareThreeWayDataImpl<ThreeWayCmp<int>, ThreeWayCmp<int>,
Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Int()
{
lexicographicalCompareThreeWayImpl<ThreeWayCmp<int>, ThreeWayCmp<int>,
Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Float_data()
{
lexicographicalCompareThreeWayDataImpl<ThreeWayCmp<float>, ThreeWayCmp<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Float()
{
lexicographicalCompareThreeWayImpl<ThreeWayCmp<float>, ThreeWayCmp<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Weak_data()
{
lexicographicalCompareThreeWayDataImpl<ThreeWayCmp<Weak>, ThreeWayCmp<Weak>,
Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_ThreeWayCmp_Weak()
{
lexicographicalCompareThreeWayImpl<ThreeWayCmp<Weak>, ThreeWayCmp<Weak>,
Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Int_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<int>, ThreeWayCmp<int>,
Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Int()
{
lexicographicalCompareThreeWayImpl<LessOnly<int>, ThreeWayCmp<int>,
Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Float_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<float>, ThreeWayCmp<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Float()
{
lexicographicalCompareThreeWayImpl<LessOnly<float>, ThreeWayCmp<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Weak_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<Weak>, ThreeWayCmp<Weak>,
Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Mixed_Weak()
{
lexicographicalCompareThreeWayImpl<LessOnly<Weak>, ThreeWayCmp<Weak>,
Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Int_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<int>, LessOnly<int>, Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Int()
{
lexicographicalCompareThreeWayComparatorImpl<LessOnly<int>, LessOnly<int>,
Qt::strong_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Float_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<float>, LessOnly<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Float()
{
lexicographicalCompareThreeWayComparatorImpl<LessOnly<float>, LessOnly<float>,
Qt::partial_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Weak_data()
{
lexicographicalCompareThreeWayDataImpl<LessOnly<Weak>, LessOnly<Weak>, Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Comparator_Weak()
{
lexicographicalCompareThreeWayComparatorImpl<LessOnly<Weak>, LessOnly<Weak>,
Qt::weak_ordering>();
}
void tst_QCompareHelpers::lexicographicalCompareThreeWay_Pointers()
{
constexpr std::array<int, 3> a = {42, 0, 17}; // the actual values do not matter
{
const QList<const int*> lhs{&a[0], &a[1], &a[2]};
const QList<const int*> rhs{&a[0], &a[1], &a[2]};
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
QCOMPARE_EQ(res, Qt::strong_ordering::equivalent);
}
{
const QList<const int*> lhs{&a[0], &a[1], &a[2]};
const QList<const int*> rhs{&a[0], &a[2]};
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
QCOMPARE_EQ(res, Qt::strong_ordering::less);
}
{
const QList<const int*> lhs{&a[0], &a[2], &a[1]};
const QList<const int*> rhs{&a[0], &a[1], &a[2]};
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
QCOMPARE_EQ(res, Qt::strong_ordering::greater);
}
{
const QList<const int*> lhs{&a[0], &a[1], &a[2], &a[0]};
const QList<const int*> rhs{&a[0], &a[1], &a[2]};
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(lhs.begin(), lhs.end(),
rhs.begin(), rhs.end());
QCOMPARE_EQ(res, Qt::strong_ordering::greater);
}
}
struct NonCopyMove
{
float val;
constexpr NonCopyMove(float f) : val(f) {}
Q_DISABLE_COPY_MOVE(NonCopyMove)
private:
friend auto compareThreeWay(const NonCopyMove &lhs, const NonCopyMove &rhs)
{
return Qt::compareThreeWay(lhs.val, rhs.val);
}
};
void tst_QCompareHelpers::lexicographicalCompareThreeWay_NonCopyMove()
{
constexpr std::array a1 = {NonCopyMove{1.f}, NonCopyMove{2.f}, NonCopyMove{3.f}};
constexpr std::array a2 = {NonCopyMove{1.f}, NonCopyMove{3.f}, NonCopyMove{2.f}};
constexpr std::array a3 = {NonCopyMove{std::numeric_limits<float>::quiet_NaN()},
NonCopyMove{2.f}, NonCopyMove{3.f}};
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a1.begin(), a1.end());
QCOMPARE_EQ(res, Qt::partial_ordering::equivalent);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a2.begin(), a2.end());
QCOMPARE_EQ(res, Qt::partial_ordering::less);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a2.begin(), a2.end(),
a1.begin(), a1.end());
QCOMPARE_EQ(res, Qt::partial_ordering::greater);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a3.begin(), a3.end());
QCOMPARE_EQ(res, Qt::partial_ordering::unordered);
}
}
struct WithCustomPointerCompareThreeWayHelper
{
float val;
private:
friend auto compareThreeWay(const WithCustomPointerCompareThreeWayHelper *lhs,
const WithCustomPointerCompareThreeWayHelper *rhs)
{
if (lhs && rhs)
return Qt::compareThreeWay(lhs->val, rhs->val);
else if (lhs)
return Qt::partial_ordering::greater;
else
return Qt::partial_ordering::less;
}
};
static_assert(QtOrderingPrivate::HasCustomCompareThreeWay<WithCustomPointerCompareThreeWayHelper*>::value);
static_assert(!QtOrderingPrivate::HasCustomCompareThreeWay<int*>::value);
void tst_QCompareHelpers::lexicographicalCompareThreeWay_CustomPointerHelper()
{
const WithCustomPointerCompareThreeWayHelper val1{1.f};
const WithCustomPointerCompareThreeWayHelper val2{2.f};
const WithCustomPointerCompareThreeWayHelper val3{3.f};
const WithCustomPointerCompareThreeWayHelper nan{std::numeric_limits<float>::quiet_NaN()};
const std::array a1 = {&val1, &val2, &val3};
const std::array a2 = {&val1, &val3, &val2};
const std::array a3 = {&nan, &val2, &val3};
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a1.begin(), a1.end());
QCOMPARE_EQ(res, Qt::partial_ordering::equivalent);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a2.begin(), a2.end());
QCOMPARE_EQ(res, Qt::partial_ordering::less);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a2.begin(), a2.end(),
a1.begin(), a1.end());
QCOMPARE_EQ(res, Qt::partial_ordering::greater);
}
{
const auto res = QtOrderingPrivate::lexicographicalCompareThreeWay(a1.begin(), a1.end(),
a3.begin(), a3.end());
QCOMPARE_EQ(res, Qt::partial_ordering::unordered);
}
}