From 45cf0cf5135e653baaf689f51b3c6338d848c16e Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 16 Oct 2020 16:15:02 +0200 Subject: [PATCH] QList: make (last)IndexOf and contains function templates There's no reason why they shouldn't be; one might want to do a lookup passing an object which is comparable with the list's value type (e.g. search with a QByteArrayView needle into a QByteArrayList haystack). Insofar we've had to add overloads to QListSpecialMethods for all these cases, which clearly doesn't scale and creates top-tier and low-tier lists. There is one downside, namely, calling QList::indexOf(B) for a B for which there isn't an operator==(A, B) but only a conversion towards A. Before, B was converted only once (at call site), now it's converted at every call of operator==. In general: such types are broken and should be fixed on their own. However let's avoid a possible regression in client code, so I've left the QString overloads in QStringList in. To get there: centralize the implementation of those methods in a empty base class, which gets then inherited by QListSpecialMethods, which is inherited by QList. This is there are still special methods that may want to overload contains, e.g. QStringList which also passes a case sensitivity). The only breakages comes from code that was already broken, for instance mixing signed and unsigned types, and the beauty of this is that now we *detect* that instead of silently ignoring. QVLA and other QList methods will be tackled in future commits. [ChangeLog][QtCore][QList] The indexOf, lastIndexOf and contains methods now take an object of any datatype -- and not just the list's own value type. This allows for heterogenous lookup in QLists. Change-Id: Ib34812217eb2b0f926fad1fc195b33758196941c Reviewed-by: Lars Knoll --- src/corelib/text/qbytearraylist.h | 16 +++------ src/corelib/text/qstringlist.cpp | 49 --------------------------- src/corelib/text/qstringlist.h | 19 +++-------- src/corelib/tools/qlist.h | 55 ++++++++++++++++++++++--------- src/corelib/tools/qlist.qdoc | 6 ++-- 5 files changed, 50 insertions(+), 95 deletions(-) diff --git a/src/corelib/text/qbytearraylist.h b/src/corelib/text/qbytearraylist.h index 25f4395a5d6..e00586291f6 100644 --- a/src/corelib/text/qbytearraylist.h +++ b/src/corelib/text/qbytearraylist.h @@ -63,7 +63,7 @@ namespace QtPrivate { #ifdef Q_CLANG_QDOC class QByteArrayList : public QList #else -template <> struct QListSpecialMethods +template <> struct QListSpecialMethods : QListSpecialMethodsBase #endif { #ifndef Q_CLANG_QDOC @@ -71,12 +71,9 @@ protected: ~QListSpecialMethods() = default; #endif public: - qsizetype indexOf(const QByteArray &ba, qsizetype from = 0) const noexcept - { return QtPrivate::indexOf(*self(), ba, from); } - qsizetype lastIndexOf(const QByteArray &ba, qsizetype from = -1) const noexcept - { return QtPrivate::lastIndexOf(*self(), ba, from); } - bool contains(const QByteArray &ba) const noexcept - { return indexOf(ba) != -1; } + using QListSpecialMethodsBase::indexOf; + using QListSpecialMethodsBase::lastIndexOf; + using QListSpecialMethodsBase::contains; inline QByteArray join() const { return QtPrivate::QByteArrayList_join(self(), nullptr, 0); } @@ -84,11 +81,6 @@ public: { return QtPrivate::QByteArrayList_join(self(), sep.constData(), sep.size()); } inline QByteArray join(char sep) const { return QtPrivate::QByteArrayList_join(self(), &sep, 1); } - -private: - typedef QList Self; - Self *self() { return static_cast(this); } - const Self *self() const { return static_cast(this); } }; QT_END_NAMESPACE diff --git a/src/corelib/text/qstringlist.cpp b/src/corelib/text/qstringlist.cpp index 233f7653558..c3957503763 100644 --- a/src/corelib/text/qstringlist.cpp +++ b/src/corelib/text/qstringlist.cpp @@ -369,55 +369,6 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str, return stringList_contains(*that, str, cs); } -/*! - \fn bool QStringList::indexOf(QStringView str, qsizetype from) const - \overload - \since 5.13 - - Returns the index position of the first occurrence of \a str in - the list, searching forward from index position \a from. Returns - -1 if no item matched. - - \sa lastIndexOf(), contains() - */ - -/*! - \fn bool QStringList::indexOf(QLatin1String str, qsizetype from) const - \overload - \since 5.13 - - Returns the index position of the first occurrence of \a str in - the list, searching forward from index position \a from. Returns - -1 if no item matched. - - \sa lastIndexOf(), contains() - */ - -/*! - \fn bool QStringList::lastIndexOf(QStringView str, qsizetype from) const - \overload - \since 5.13 - - Returns the index position of the last occurrence of \a str in - the list, searching backward from index position \a from. If \a - from is -1 (the default), the search starts at the last item. - Returns -1 if no item matched. - - \sa indexOf(), contains() - */ - -/*! - \fn bool QStringList::lastIndexOf(QLatin1String str, qsizetype from) const - \overload - \since 5.13 - - Returns the index position of the last occurrence of \a str in - the list, searching backward from index position \a from. If \a - from is -1 (the default), the search starts at the last item. - Returns -1 if no item matched. - - \sa indexOf(), contains() - */ #if QT_CONFIG(regularexpression) /*! diff --git a/src/corelib/text/qstringlist.h b/src/corelib/text/qstringlist.h index 2894fa78cf0..5ec95036be6 100644 --- a/src/corelib/text/qstringlist.h +++ b/src/corelib/text/qstringlist.h @@ -82,7 +82,7 @@ namespace QtPrivate { #ifdef Q_QDOC class QStringList : public QList #else -template <> struct QListSpecialMethods +template <> struct QListSpecialMethods : QListSpecialMethodsBase #endif { #ifdef Q_QDOC @@ -100,10 +100,6 @@ public: QStringList &operator<<(const QList &other); private: #endif - inline QStringList *self() - { return static_cast(this); } - inline const QStringList *self() const - { return static_cast(this); } public: inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive) @@ -147,22 +143,15 @@ public: return *self(); } #endif + using QListSpecialMethodsBase::contains; + using QListSpecialMethodsBase::indexOf; + using QListSpecialMethodsBase::lastIndexOf; inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::QStringList_contains(self(), str, cs); } inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::QStringList_contains(self(), str, cs); } - inline qsizetype indexOf(QStringView str, qsizetype from = 0) const noexcept - { return QtPrivate::indexOf(*self(), str, from); } - inline qsizetype indexOf(QLatin1String str, qsizetype from = 0) const noexcept - { return QtPrivate::indexOf(*self(), str, from); } - - inline qsizetype lastIndexOf(QStringView str, qsizetype from = -1) const noexcept - { return QtPrivate::lastIndexOf(*self(), str, from); } - inline qsizetype lastIndexOf(QLatin1String str, qsizetype from = -1) const noexcept - { return QtPrivate::lastIndexOf(*self(), str, from); } - #if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return QtPrivate::QStringList_contains(self(), str, cs); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 6931bd6cbcc..38cc0ed348e 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -58,18 +58,35 @@ namespace QtPrivate { template qsizetype lastIndexOf(const QList &list, const U &u, qsizetype from) noexcept; } -template struct QListSpecialMethods +template struct QListSpecialMethodsBase +{ +protected: + ~QListSpecialMethodsBase() = default; + + using Self = QList; + Self *self() { return static_cast(this); } + const Self *self() const { return static_cast(this); } + +public: + template + qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept; + template + qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept; + + template + bool contains(const AT &t) const noexcept + { + return self()->indexOf(t) != -1; + } +}; +template struct QListSpecialMethods : QListSpecialMethodsBase { protected: ~QListSpecialMethods() = default; public: - qsizetype indexOf(const T &t, qsizetype from = 0) const noexcept; - qsizetype lastIndexOf(const T &t, qsizetype from = -1) const noexcept; - - bool contains(const T &t) const noexcept - { - return indexOf(t) != -1; - } + using QListSpecialMethodsBase::indexOf; + using QListSpecialMethodsBase::lastIndexOf; + using QListSpecialMethodsBase::contains; }; template <> struct QListSpecialMethods; template <> struct QListSpecialMethods; @@ -327,12 +344,16 @@ public: using QListSpecialMethods::indexOf; using QListSpecialMethods::lastIndexOf; #else - qsizetype indexOf(const T &t, qsizetype from = 0) const noexcept; - qsizetype lastIndexOf(const T &t, qsizetype from = -1) const noexcept; - bool contains(const T &t) const noexcept; + template + qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept; + template + qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept; + template + bool contains(const AT &t) const noexcept; #endif - qsizetype count(parameter_type t) const noexcept + template + qsizetype count(const AT &t) const noexcept { return qsizetype(std::count(&*cbegin(), &*cend(), t)); } @@ -790,15 +811,17 @@ qsizetype lastIndexOf(const QList &vector, const U &u, qsizetype from) noexce } template -qsizetype QListSpecialMethods::indexOf(const T &t, qsizetype from) const noexcept +template +qsizetype QListSpecialMethodsBase::indexOf(const AT &t, qsizetype from) const noexcept { - return QtPrivate::indexOf(*static_cast *>(this), t, from); + return QtPrivate::indexOf(*self(), t, from); } template -qsizetype QListSpecialMethods::lastIndexOf(const T &t, qsizetype from) const noexcept +template +qsizetype QListSpecialMethodsBase::lastIndexOf(const AT &t, qsizetype from) const noexcept { - return QtPrivate::lastIndexOf(*static_cast *>(this), t, from); + return QtPrivate::lastIndexOf(*self(), t, from); } template diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc index 52ac5360c87..84296e8e47e 100644 --- a/src/corelib/tools/qlist.qdoc +++ b/src/corelib/tools/qlist.qdoc @@ -952,7 +952,7 @@ \sa resize() */ -/*! \fn template qsizetype QList::indexOf(const T &value, qsizetype from = 0) const +/*! \fn template template qsizetype QList::indexOf(const AT &value, qsizetype from = 0) const Returns the index position of the first occurrence of \a value in the list, searching forward from index position \a from. @@ -967,7 +967,7 @@ \sa lastIndexOf(), contains() */ -/*! \fn template qsizetype QList::lastIndexOf(const T &value, qsizetype from = -1) const +/*! \fn template template qsizetype QList::lastIndexOf(const AT &value, qsizetype from = -1) const Returns the index position of the last occurrence of the value \a value in the list, searching backward from index position \a @@ -983,7 +983,7 @@ \sa indexOf() */ -/*! \fn template bool QList::contains(const T &value) const +/*! \fn template template bool QList::contains(const AT &value) const Returns \c true if the list contains an occurrence of \a value; otherwise returns \c false.