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>
This commit is contained in:
Marc Mutz 2014-08-19 23:30:38 +02:00
parent 40d6e8adf5
commit 18885297de

View File

@ -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)
@ -940,6 +946,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());
@ -949,8 +961,22 @@ Q_OUTOFLINE_TEMPLATE bool QList<T>::contains(const T &t) const
return false;
}
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());
@ -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)