QList: implement operator<=> for iterators

This fixes an annoying warning with MSVC where it did already compile
  iterator <=> iterator
by way of the deprecated operator*(). GCC and Clang did not compile the
above, though they do compile the other ordering operators.

Fixes: QTBUG-120924
Change-Id: Ie13bf48bc506e7dd719efffdeae55f0735148976
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Rym Bouabid <rym.bouabid@qt.io>
This commit is contained in:
Thiago Macieira 2025-03-31 11:42:32 -04:00
parent 3f55ac90fc
commit 750a0b5ef6
3 changed files with 51 additions and 2 deletions

View File

@ -142,6 +142,10 @@ public:
inline T &operator*() const { return *i; } inline T &operator*() const { return *i; }
inline T *operator->() const { return i; } inline T *operator->() const { return i; }
inline T &operator[](qsizetype j) const { return *(i + j); } inline T &operator[](qsizetype j) const { return *(i + j); }
#ifdef __cpp_lib_three_way_comparison
friend constexpr auto operator<=>(iterator, iterator) noexcept = default;
friend constexpr bool operator==(iterator, iterator) noexcept = default;
#else
inline constexpr bool operator==(iterator o) const { return i == o.i; } inline constexpr bool operator==(iterator o) const { return i == o.i; }
inline constexpr bool operator!=(iterator o) const { return i != o.i; } inline constexpr bool operator!=(iterator o) const { return i != o.i; }
inline constexpr bool operator<(iterator other) const { return i < other.i; } inline constexpr bool operator<(iterator other) const { return i < other.i; }
@ -154,6 +158,7 @@ public:
inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; } inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
inline constexpr bool operator>(const_iterator other) const { return i > other.i; } inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; } inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
#endif // __cpp_lib_three_way_comparison
inline constexpr bool operator==(pointer p) const { return i == p; } inline constexpr bool operator==(pointer p) const { return i == p; }
inline constexpr bool operator!=(pointer p) const { return i != p; } inline constexpr bool operator!=(pointer p) const { return i != p; }
inline iterator &operator++() { ++i; return *this; } inline iterator &operator++() { ++i; return *this; }
@ -213,6 +218,14 @@ public:
inline const T &operator*() const { return *i; } inline const T &operator*() const { return *i; }
inline const T *operator->() const { return i; } inline const T *operator->() const { return i; }
inline const T &operator[](qsizetype j) const { return *(i + j); } inline const T &operator[](qsizetype j) const { return *(i + j); }
#ifdef __cpp_lib_three_way_comparison
friend constexpr auto operator<=>(const_iterator, const_iterator) noexcept = default;
friend constexpr auto operator<=>(const_iterator a, iterator b) noexcept
{ return a <=> const_iterator(b); }
friend constexpr bool operator==(const_iterator, const_iterator) noexcept = default;
friend constexpr bool operator==(const_iterator a, iterator b) noexcept
{ return a == const_iterator(b); }
#else
inline constexpr bool operator==(const_iterator o) const { return i == o.i; } inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
inline constexpr bool operator!=(const_iterator o) const { return i != o.i; } inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
inline constexpr bool operator<(const_iterator other) const { return i < other.i; } inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
@ -225,6 +238,7 @@ public:
inline constexpr bool operator<=(iterator other) const { return i <= other.i; } inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
inline constexpr bool operator>(iterator other) const { return i > other.i; } inline constexpr bool operator>(iterator other) const { return i > other.i; }
inline constexpr bool operator>=(iterator other) const { return i >= other.i; } inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
#endif // __cpp_lib_three_way_comparison
inline constexpr bool operator==(pointer p) const { return i == p; } inline constexpr bool operator==(pointer p) const { return i == p; }
inline constexpr bool operator!=(pointer p) const { return i != p; } inline constexpr bool operator!=(pointer p) const { return i != p; }
inline const_iterator &operator++() { ++i; return *this; } inline const_iterator &operator++() { ++i; return *this; }

View File

@ -18,6 +18,7 @@ qt_internal_add_test(tst_qlist
QT_NO_STRICT_QLIST_ITERATORS # doesn't exist, except for this test QT_NO_STRICT_QLIST_ITERATORS # doesn't exist, except for this test
LIBRARIES LIBRARIES
Qt::CorePrivate Qt::CorePrivate
Qt::TestPrivate
) )
qt_internal_add_test(tst_qlist_strict_iterators qt_internal_add_test(tst_qlist_strict_iterators
@ -28,6 +29,7 @@ qt_internal_add_test(tst_qlist_strict_iterators
tst_QList=tst_QList_strict_iterators tst_QList=tst_QList_strict_iterators
LIBRARIES LIBRARIES
Qt::CorePrivate Qt::CorePrivate
Qt::TestPrivate
) )
## Scopes: ## Scopes:

View File

@ -6,13 +6,14 @@
# undef QT_STRICT_QLIST_ITERATORS # undef QT_STRICT_QLIST_ITERATORS
# endif # endif
#endif #endif
#include <qlist.h>
#include <QTest> #include <QTest>
#include <QAtomicInt> #include <QAtomicInt>
#include <QAtomicScopedValueRollback>
#include <QThread> #include <QThread>
#include <QSemaphore> #include <QSemaphore>
#include <QAtomicScopedValueRollback> #include <QtTest/private/qcomparisontesthelper_p.h>
#include <qlist.h>
#include <cstdio> #include <cstdio>
#include <QtCore/q20memory.h> #include <QtCore/q20memory.h>
@ -2616,10 +2617,23 @@ void tst_QList::iterators() const
QCOMPARE(v.begin(), v.end()); QCOMPARE(v.begin(), v.end());
QCOMPARE(v.rbegin(), v.rend()); QCOMPARE(v.rbegin(), v.rend());
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.end(), Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.rend(), Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(v.cbegin(), v.end(), Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(v.crbegin(), v.rend(), Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.cend(), Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.crend(), Qt::strong_ordering::equal);
qsizetype idx = 0; qsizetype idx = 0;
for (; idx < 10; ++idx) for (; idx < 10; ++idx)
v.push_back(idx); v.push_back(idx);
QCOMPARE_LT(v.begin(), v.end());
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.rend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.cbegin(), v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.crbegin(), v.rend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.cend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.crend(), Qt::strong_ordering::less);
// stl-style iterators // stl-style iterators
idx = 0; idx = 0;
@ -2629,6 +2643,10 @@ void tst_QList::iterators() const
std::advance(it, 7); std::advance(it, 7);
idx += 7; idx += 7;
QT_TEST_ALL_COMPARISON_OPS(it, v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(it, v.cend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.begin(), it, Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.cbegin(), it, Qt::strong_ordering::less);
QCOMPARE(*it, idx); QCOMPARE(*it, idx);
// idx == 7 // idx == 7
@ -2765,8 +2783,19 @@ void tst_QList::constIterators() const
QCOMPARE(constEmptyList.constBegin(), constEmptyList.cbegin()); QCOMPARE(constEmptyList.constBegin(), constEmptyList.cbegin());
QCOMPARE(constEmptyList.constEnd(), constEmptyList.cend()); QCOMPARE(constEmptyList.constEnd(), constEmptyList.cend());
QVERIFY(!constEmptyList.isDetached()); QVERIFY(!constEmptyList.isDetached());
QT_TEST_ALL_COMPARISON_OPS(constEmptyList.begin(), constEmptyList.end(),
Qt::strong_ordering::equal);
QT_TEST_ALL_COMPARISON_OPS(constEmptyList.rbegin(), constEmptyList.rend(),
Qt::strong_ordering::equal);
const QList<int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; const QList<int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
QCOMPARE_LT(v.begin(), v.end());
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.rend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.cbegin(), v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.crbegin(), v.rend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.begin(), v.cend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.rbegin(), v.crend(), Qt::strong_ordering::less);
// stl-style iterators // stl-style iterators
qsizetype idx = 0; qsizetype idx = 0;
@ -2776,6 +2805,10 @@ void tst_QList::constIterators() const
std::advance(it, 7); std::advance(it, 7);
idx += 7; idx += 7;
QT_TEST_ALL_COMPARISON_OPS(it, v.end(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(it, v.cend(), Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.begin(), it, Qt::strong_ordering::less);
QT_TEST_ALL_COMPARISON_OPS(v.cbegin(), it, Qt::strong_ordering::less);
QCOMPARE(*it, idx); QCOMPARE(*it, idx);
// idx == 7 // idx == 7