diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2014-08-19 23:30:38 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2015-02-17 15:05:15 +0000 |
commit | 18885297de880493831f63d20a8d45c6689a01b8 (patch) | |
tree | c4a204b499d37cc051b0f11916f50d38123b6797 | |
parent | 40d6e8adf5e3cc45b3bd4a94ad3b57f9444e447f (diff) |
QList: share the implementations of contains()/count() with QVector where possible
If QList data-layout-compatible with QVector and a C array, implement count()
via std::count() and contains() via std::find() and use const_pointer
instead of const_iterator as the iterators. This essentially makes
the QVector and QList implementations identical to each other, at least for
important cases such as QString.
To switch between the different implementations, use tag dispatching instead
of the previously used technique "use 'if' as if it were 'static if'", which
imposes accidental requirements on the element types (something that esp.
QVector is plagued with).
Change-Id: I6caf74442a22059676b5bf115a6089768f3a0952
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/tools/qlist.h | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 255816d0ba..5d6cf9fe15 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -377,6 +377,12 @@ private: { return (constBegin().i <= i.i) && (i.i <= constEnd().i); } + +private: + inline bool contains_impl(const T &, QListData::NotArrayCompatibleLayout) const; + inline bool contains_impl(const T &, QListData::ArrayCompatibleLayout) const; + inline int count_impl(const T &, QListData::NotArrayCompatibleLayout) const; + inline int count_impl(const T &, QListData::ArrayCompatibleLayout) const; }; #if defined(Q_CC_BOR) @@ -941,6 +947,12 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const template <typename T> Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const { + return contains_impl(t, MemoryLayout()); +} + +template <typename T> +inline bool QList<T>::contains_impl(const T &t, QListData::NotArrayCompatibleLayout) const +{ Node *e = reinterpret_cast<Node *>(p.end()); Node *i = reinterpret_cast<Node *>(p.begin()); for (; i != e; ++i) @@ -950,8 +962,22 @@ Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const } template <typename T> +inline bool QList<T>::contains_impl(const T &t, QListData::ArrayCompatibleLayout) const +{ + const T *b = reinterpret_cast<const T*>(p.begin()); + const T *e = reinterpret_cast<const T*>(p.end()); + return std::find(b, e, t) != e; +} + +template <typename T> Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const { + return this->count_impl(t, MemoryLayout()); +} + +template <typename T> +inline int QList<T>::count_impl(const T &t, QListData::NotArrayCompatibleLayout) const +{ int c = 0; Node *e = reinterpret_cast<Node *>(p.end()); Node *i = reinterpret_cast<Node *>(p.begin()); @@ -961,6 +987,14 @@ Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const return c; } +template <typename T> +inline int QList<T>::count_impl(const T &t, QListData::ArrayCompatibleLayout) const +{ + return int(std::count(reinterpret_cast<const T*>(p.begin()), + reinterpret_cast<const T*>(p.end()), + t)); +} + Q_DECLARE_SEQUENTIAL_ITERATOR(List) Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List) |