/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QLIST_H #define QLIST_H #include #include #include #include #include #ifdef Q_COMPILER_INITIALIZER_LISTS #include #endif #include #include #include #include QT_BEGIN_NAMESPACE template class QVector; template class QSet; struct Q_CORE_EXPORT QListData { struct Data { QtPrivate::RefCount ref; int alloc, begin, end; void *array[1]; }; enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; Data *detach(int alloc); Data *detach_grow(int *i, int n); void realloc(int alloc); inline void dispose() { dispose(d); } static void dispose(Data *d); static const Data shared_null; Data *d; void **erase(void **xi); void **append(int n); void **append(); void **append(const QListData &l); void **prepend(); void **insert(int i); void remove(int i); void remove(int i, int n); void move(int from, int to); inline int size() const { return d->end - d->begin; } inline bool isEmpty() const { return d->end == d->begin; } inline void **at(int i) const { return d->array + d->begin + i; } inline void **begin() const { return d->array + d->begin; } inline void **end() const { return d->array + d->end; } }; template class QList { struct Node { void *v; #if defined(Q_CC_BOR) Q_INLINE_TEMPLATE T &t(); #else Q_INLINE_TEMPLATE T &t() { return *reinterpret_cast(QTypeInfo::isLarge || QTypeInfo::isStatic ? v : this); } #endif }; union { QListData p; QListData::Data *d; }; public: inline QList() : d(const_cast(&QListData::shared_null)) { } QList(const QList &l); ~QList(); QList &operator=(const QList &l); #ifdef Q_COMPILER_RVALUE_REFS inline QList(QList &&other) : d(other.d) { other.d = const_cast(&QListData::shared_null); } inline QList &operator=(QList &&other) { qSwap(d, other.d); return *this; } #endif inline void swap(QList &other) { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) : d(const_cast(&QListData::shared_null)) { qCopy(args.begin(), args.end(), std::back_inserter(*this)); } #endif bool operator==(const QList &l) const; inline bool operator!=(const QList &l) const { return !(*this == l); } inline int size() const { return p.size(); } inline void detach() { if (d->ref.isShared()) detach_helper(); } inline void detachShared() { // The "this->" qualification is needed for GCCE. if (d->ref.isShared() && this->d != &QListData::shared_null) detach_helper(); } inline bool isDetached() const { return !d->ref.isShared(); } inline void setSharable(bool sharable) { if (sharable == d->ref.isSharable()) return; if (!sharable) detach(); if (d != &QListData::shared_null) d->ref.setSharable(sharable); } inline bool isSharedWith(const QList &other) const { return d == other.d; } inline bool isEmpty() const { return p.isEmpty(); } void clear(); const T &at(int i) const; const T &operator[](int i) const; T &operator[](int i); void reserve(int size); void append(const T &t); void append(const QList &t); void prepend(const T &t); void insert(int i, const T &t); void replace(int i, const T &t); void removeAt(int i); int removeAll(const T &t); bool removeOne(const T &t); T takeAt(int i); T takeFirst(); T takeLast(); void move(int from, int to); void swap(int i, int j); int indexOf(const T &t, int from = 0) const; int lastIndexOf(const T &t, int from = -1) const; bool contains(const T &t) const; int count(const T &t) const; class const_iterator; class iterator { public: Node *i; typedef std::random_access_iterator_tag iterator_category; typedef qptrdiff difference_type; typedef T value_type; typedef T *pointer; typedef T &reference; inline iterator() : i(0) {} inline iterator(Node *n) : i(n) {} inline iterator(const iterator &o): i(o.i){} inline T &operator*() const { return i->t(); } inline T *operator->() const { return &i->t(); } inline T &operator[](int j) const { return i[j].t(); } inline bool operator==(const iterator &o) const { return i == o.i; } inline bool operator!=(const iterator &o) const { return i != o.i; } inline bool operator<(const iterator& other) const { return i < other.i; } inline bool operator<=(const iterator& other) const { return i <= other.i; } inline bool operator>(const iterator& other) const { return i > other.i; } inline bool operator>=(const iterator& other) const { return i >= other.i; } #ifndef QT_STRICT_ITERATORS inline bool operator==(const const_iterator &o) const { return i == o.i; } inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline bool operator<(const const_iterator& other) const { return i < other.i; } inline bool operator<=(const const_iterator& other) const { return i <= other.i; } inline bool operator>(const const_iterator& other) const { return i > other.i; } inline bool operator>=(const const_iterator& other) const { return i >= other.i; } #endif inline iterator &operator++() { ++i; return *this; } inline iterator operator++(int) { Node *n = i; ++i; return n; } inline iterator &operator--() { i--; return *this; } inline iterator operator--(int) { Node *n = i; i--; return n; } inline iterator &operator+=(int j) { i+=j; return *this; } inline iterator &operator-=(int j) { i-=j; return *this; } inline iterator operator+(int j) const { return iterator(i+j); } inline iterator operator-(int j) const { return iterator(i-j); } inline int operator-(iterator j) const { return int(i - j.i); } }; friend class iterator; class const_iterator { public: Node *i; typedef std::random_access_iterator_tag iterator_category; typedef qptrdiff difference_type; typedef T value_type; typedef const T *pointer; typedef const T &reference; inline const_iterator() : i(0) {} inline const_iterator(Node *n) : i(n) {} inline const_iterator(const const_iterator &o): i(o.i) {} #ifdef QT_STRICT_ITERATORS inline explicit const_iterator(const iterator &o): i(o.i) {} #else inline const_iterator(const iterator &o): i(o.i) {} #endif inline const T &operator*() const { return i->t(); } inline const T *operator->() const { return &i->t(); } inline const T &operator[](int j) const { return i[j].t(); } inline bool operator==(const const_iterator &o) const { return i == o.i; } inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline bool operator<(const const_iterator& other) const { return i < other.i; } inline bool operator<=(const const_iterator& other) const { return i <= other.i; } inline bool operator>(const const_iterator& other) const { return i > other.i; } inline bool operator>=(const const_iterator& other) const { return i >= other.i; } inline const_iterator &operator++() { ++i; return *this; } inline const_iterator operator++(int) { Node *n = i; ++i; return n; } inline const_iterator &operator--() { i--; return *this; } inline const_iterator operator--(int) { Node *n = i; i--; return n; } inline const_iterator &operator+=(int j) { i+=j; return *this; } inline const_iterator &operator-=(int j) { i-=j; return *this; } inline const_iterator operator+(int j) const { return const_iterator(i+j); } inline const_iterator operator-(int j) const { return const_iterator(i-j); } inline int operator-(const_iterator j) const { return i - j.i; } }; friend class const_iterator; // stl style inline iterator begin() { detach(); return reinterpret_cast(p.begin()); } inline const_iterator begin() const { return reinterpret_cast(p.begin()); } inline const_iterator cbegin() const { return reinterpret_cast(p.begin()); } inline const_iterator constBegin() const { return reinterpret_cast(p.begin()); } inline iterator end() { detach(); return reinterpret_cast(p.end()); } inline const_iterator end() const { return reinterpret_cast(p.end()); } inline const_iterator cend() const { return reinterpret_cast(p.end()); } inline const_iterator constEnd() const { return reinterpret_cast(p.end()); } iterator insert(iterator before, const T &t); iterator erase(iterator pos); iterator erase(iterator first, iterator last); // more Qt typedef iterator Iterator; typedef const_iterator ConstIterator; inline int count() const { return p.size(); } inline int length() const { return p.size(); } // Same as count() inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } inline const T& first() const { Q_ASSERT(!isEmpty()); return at(0); } T& last() { Q_ASSERT(!isEmpty()); return *(--end()); } const T& last() const { Q_ASSERT(!isEmpty()); return at(count() - 1); } inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); } inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); } inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; } QList mid(int pos, int length = -1) const; T value(int i) const; T value(int i, const T &defaultValue) const; // stl compatibility inline void push_back(const T &t) { append(t); } inline void push_front(const T &t) { prepend(t); } inline T& front() { return first(); } inline const T& front() const { return first(); } inline T& back() { return last(); } inline const T& back() const { return last(); } inline void pop_front() { removeFirst(); } inline void pop_back() { removeLast(); } inline bool empty() const { return isEmpty(); } typedef int size_type; typedef T value_type; typedef value_type *pointer; typedef const value_type *const_pointer; typedef value_type &reference; typedef const value_type &const_reference; typedef qptrdiff difference_type; // comfort QList &operator+=(const QList &l); inline QList operator+(const QList &l) const { QList n = *this; n += l; return n; } inline QList &operator+=(const T &t) { append(t); return *this; } inline QList &operator<< (const T &t) { append(t); return *this; } inline QList &operator<<(const QList &l) { *this += l; return *this; } QVector toVector() const; QSet toSet() const; static QList fromVector(const QVector &vector); static QList fromSet(const QSet &set); static inline QList fromStdList(const std::list &list) { QList tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } inline std::list toStdList() const { std::list tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } private: Node *detach_helper_grow(int i, int n); void detach_helper(int alloc); void detach_helper(); void dealloc(QListData::Data *d); void node_construct(Node *n, const T &t); void node_destruct(Node *n); void node_copy(Node *from, Node *to, Node *src); void node_destruct(Node *from, Node *to); }; #if defined(Q_CC_BOR) template Q_INLINE_TEMPLATE T &QList::Node::t() { return QTypeInfo::isLarge || QTypeInfo::isStatic ? *(T*)v:*(T*)this; } #endif template Q_INLINE_TEMPLATE void QList::node_construct(Node *n, const T &t) { if (QTypeInfo::isLarge || QTypeInfo::isStatic) n->v = new T(t); else if (QTypeInfo::isComplex) new (n) T(t); #if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__) // This violates pointer aliasing rules, but it is known to be safe (and silent) // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which // set the same define are assumed to be safe. else *reinterpret_cast(n) = t; #else // This is always safe, but penaltizes unoptimized builds a lot. else ::memcpy(n, static_cast(&t), sizeof(T)); #endif } template Q_INLINE_TEMPLATE void QList::node_destruct(Node *n) { if (QTypeInfo::isLarge || QTypeInfo::isStatic) delete reinterpret_cast(n->v); else if (QTypeInfo::isComplex) reinterpret_cast(n)->~T(); } template Q_INLINE_TEMPLATE void QList::node_copy(Node *from, Node *to, Node *src) { Node *current = from; if (QTypeInfo::isLarge || QTypeInfo::isStatic) { QT_TRY { while(current != to) { current->v = new T(*reinterpret_cast(src->v)); ++current; ++src; } } QT_CATCH(...) { while (current-- != from) delete reinterpret_cast(current->v); QT_RETHROW; } } else if (QTypeInfo::isComplex) { QT_TRY { while(current != to) { new (current) T(*reinterpret_cast(src)); ++current; ++src; } } QT_CATCH(...) { while (current-- != from) (reinterpret_cast(current))->~T(); QT_RETHROW; } } else { if (src != from && to - from > 0) memcpy(from, src, (to - from) * sizeof(Node)); } } template Q_INLINE_TEMPLATE void QList::node_destruct(Node *from, Node *to) { if (QTypeInfo::isLarge || QTypeInfo::isStatic) while(from != to) --to, delete reinterpret_cast(to->v); else if (QTypeInfo::isComplex) while (from != to) --to, reinterpret_cast(to)->~T(); } template Q_INLINE_TEMPLATE QList &QList::operator=(const QList &l) { if (d != l.d) { QList tmp(l); tmp.swap(*this); } return *this; } template inline typename QList::iterator QList::insert(iterator before, const T &t) { int iBefore = int(before.i - reinterpret_cast(p.begin())); Node *n = reinterpret_cast(p.insert(iBefore)); QT_TRY { node_construct(n, t); } QT_CATCH(...) { p.remove(iBefore); QT_RETHROW; } return n; } template inline typename QList::iterator QList::erase(iterator it) { node_destruct(it.i); return reinterpret_cast(p.erase(reinterpret_cast(it.i))); } template inline const T &QList::at(int i) const { Q_ASSERT_X(i >= 0 && i < p.size(), "QList::at", "index out of range"); return reinterpret_cast(p.at(i))->t(); } template inline const T &QList::operator[](int i) const { Q_ASSERT_X(i >= 0 && i < p.size(), "QList::operator[]", "index out of range"); return reinterpret_cast(p.at(i))->t(); } template inline T &QList::operator[](int i) { Q_ASSERT_X(i >= 0 && i < p.size(), "QList::operator[]", "index out of range"); detach(); return reinterpret_cast(p.at(i))->t(); } template inline void QList::removeAt(int i) { if(i >= 0 && i < p.size()) { detach(); node_destruct(reinterpret_cast(p.at(i))); p.remove(i); } } template inline T QList::takeAt(int i) { Q_ASSERT_X(i >= 0 && i < p.size(), "QList::take", "index out of range"); detach(); Node *n = reinterpret_cast(p.at(i)); T t = n->t(); node_destruct(n); p.remove(i); return t; } template inline T QList::takeFirst() { T t = first(); removeFirst(); return t; } template inline T QList::takeLast() { T t = last(); removeLast(); return t; } template Q_OUTOFLINE_TEMPLATE void QList::reserve(int alloc) { if (d->alloc < alloc) { if (d->ref.isShared()) detach_helper(alloc); else p.realloc(alloc); } } template Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) { if (d->ref.isShared()) { Node *n = detach_helper_grow(INT_MAX, 1); QT_TRY { node_construct(n, t); } QT_CATCH(...) { --d->end; QT_RETHROW; } } else { if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.append()); QT_TRY { node_construct(n, t); } QT_CATCH(...) { --d->end; QT_RETHROW; } } else { Node *n, copy; node_construct(©, t); // t might be a reference to an object in the array QT_TRY { n = reinterpret_cast(p.append());; } QT_CATCH(...) { node_destruct(©); QT_RETHROW; } *n = copy; } } } template inline void QList::prepend(const T &t) { if (d->ref.isShared()) { Node *n = detach_helper_grow(0, 1); QT_TRY { node_construct(n, t); } QT_CATCH(...) { ++d->begin; QT_RETHROW; } } else { if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.prepend()); QT_TRY { node_construct(n, t); } QT_CATCH(...) { ++d->begin; QT_RETHROW; } } else { Node *n, copy; node_construct(©, t); // t might be a reference to an object in the array QT_TRY { n = reinterpret_cast(p.prepend());; } QT_CATCH(...) { node_destruct(©); QT_RETHROW; } *n = copy; } } } template inline void QList::insert(int i, const T &t) { if (d->ref.isShared()) { Node *n = detach_helper_grow(i, 1); QT_TRY { node_construct(n, t); } QT_CATCH(...) { p.remove(i); QT_RETHROW; } } else { if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.insert(i)); QT_TRY { node_construct(n, t); } QT_CATCH(...) { p.remove(i); QT_RETHROW; } } else { Node *n, copy; node_construct(©, t); // t might be a reference to an object in the array QT_TRY { n = reinterpret_cast(p.insert(i));; } QT_CATCH(...) { node_destruct(©); QT_RETHROW; } *n = copy; } } } template inline void QList::replace(int i, const T &t) { Q_ASSERT_X(i >= 0 && i < p.size(), "QList::replace", "index out of range"); detach(); reinterpret_cast(p.at(i))->t() = t; } template inline void QList::swap(int i, int j) { Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList::swap", "index out of range"); detach(); void *t = d->array[d->begin + i]; d->array[d->begin + i] = d->array[d->begin + j]; d->array[d->begin + j] = t; } template inline void QList::move(int from, int to) { Q_ASSERT_X(from >= 0 && from < p.size() && to >= 0 && to < p.size(), "QList::move", "index out of range"); detach(); p.move(from, to); } template Q_OUTOFLINE_TEMPLATE QList QList::mid(int pos, int alength) const { if (alength < 0 || pos + alength > size()) alength = size() - pos; if (pos == 0 && alength == size()) return *this; QList cpy; if (alength <= 0) return cpy; cpy.reserve(alength); cpy.d->end = alength; QT_TRY { cpy.node_copy(reinterpret_cast(cpy.p.begin()), reinterpret_cast(cpy.p.end()), reinterpret_cast(p.begin() + pos)); } QT_CATCH(...) { // restore the old end cpy.d->end = 0; QT_RETHROW; } return cpy; } template Q_OUTOFLINE_TEMPLATE T QList::value(int i) const { if (i < 0 || i >= p.size()) { return T(); } return reinterpret_cast(p.at(i))->t(); } template Q_OUTOFLINE_TEMPLATE T QList::value(int i, const T& defaultValue) const { return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast(p.at(i))->t()); } template Q_OUTOFLINE_TEMPLATE typename QList::Node *QList::detach_helper_grow(int i, int c) { Node *n = reinterpret_cast(p.begin()); QListData::Data *x = p.detach_grow(&i, c); QT_TRY { node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.begin() + i), n); } QT_CATCH(...) { p.dispose(); d = x; QT_RETHROW; } QT_TRY { node_copy(reinterpret_cast(p.begin() + i + c), reinterpret_cast(p.end()), n + i); } QT_CATCH(...) { node_destruct(reinterpret_cast(p.begin()), reinterpret_cast(p.begin() + i)); p.dispose(); d = x; QT_RETHROW; } if (!x->ref.deref()) dealloc(x); return reinterpret_cast(p.begin() + i); } template Q_OUTOFLINE_TEMPLATE void QList::detach_helper(int alloc) { Node *n = reinterpret_cast(p.begin()); QListData::Data *x = p.detach(alloc); QT_TRY { node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), n); } QT_CATCH(...) { p.dispose(); d = x; QT_RETHROW; } if (!x->ref.deref()) dealloc(x); } template Q_OUTOFLINE_TEMPLATE void QList::detach_helper() { detach_helper(d->alloc); } template Q_OUTOFLINE_TEMPLATE QList::QList(const QList &l) : d(l.d) { if (!d->ref.ref()) { p.detach(d->alloc); struct Cleanup { Cleanup(QListData::Data *d) : d_(d) {} ~Cleanup() { if (d_) QListData::dispose(d_); } QListData::Data *d_; } tryCatch(d); node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), reinterpret_cast(l.p.begin())); tryCatch.d_ = 0; } } template Q_OUTOFLINE_TEMPLATE QList::~QList() { if (!d->ref.deref()) dealloc(d); } template Q_OUTOFLINE_TEMPLATE bool QList::operator==(const QList &l) const { if (p.size() != l.p.size()) return false; if (d == l.d) return true; Node *i = reinterpret_cast(p.end()); Node *b = reinterpret_cast(p.begin()); Node *li = reinterpret_cast(l.p.end()); while (i != b) { --i; --li; if (!(i->t() == li->t())) return false; } return true; } template Q_OUTOFLINE_TEMPLATE void QList::dealloc(QListData::Data *data) { node_destruct(reinterpret_cast(data->array + data->begin), reinterpret_cast(data->array + data->end)); QListData::dispose(data); } template Q_OUTOFLINE_TEMPLATE void QList::clear() { *this = QList(); } template Q_OUTOFLINE_TEMPLATE int QList::removeAll(const T &_t) { int index = indexOf(_t); if (index == -1) return 0; const T t = _t; detach(); Node *i = reinterpret_cast(p.at(index)); Node *e = reinterpret_cast(p.end()); Node *n = i; node_destruct(i); while (++i != e) { if (i->t() == t) node_destruct(i); else *n++ = *i; } int removedCount = e - n; d->end -= removedCount; return removedCount; } template Q_OUTOFLINE_TEMPLATE bool QList::removeOne(const T &_t) { int index = indexOf(_t); if (index != -1) { removeAt(index); return true; } return false; } template Q_OUTOFLINE_TEMPLATE typename QList::iterator QList::erase(typename QList::iterator afirst, typename QList::iterator alast) { for (Node *n = afirst.i; n < alast.i; ++n) node_destruct(n); int idx = afirst - begin(); p.remove(idx, alast - afirst); return begin() + idx; } template Q_OUTOFLINE_TEMPLATE QList &QList::operator+=(const QList &l) { if (!l.isEmpty()) { if (isEmpty()) { *this = l; } else { Node *n = (d->ref.isShared()) ? detach_helper_grow(INT_MAX, l.size()) : reinterpret_cast(p.append(l.p)); QT_TRY { node_copy(n, reinterpret_cast(p.end()), reinterpret_cast(l.p.begin())); } QT_CATCH(...) { // restore the old end d->end -= int(reinterpret_cast(p.end()) - n); QT_RETHROW; } } } return *this; } template inline void QList::append(const QList &t) { *this += t; } template Q_OUTOFLINE_TEMPLATE int QList::indexOf(const T &t, int from) const { if (from < 0) from = qMax(from + p.size(), 0); if (from < p.size()) { Node *n = reinterpret_cast(p.at(from -1)); Node *e = reinterpret_cast(p.end()); while (++n != e) if (n->t() == t) return int(n - reinterpret_cast(p.begin())); } return -1; } template Q_OUTOFLINE_TEMPLATE int QList::lastIndexOf(const T &t, int from) const { if (from < 0) from += p.size(); else if (from >= p.size()) from = p.size()-1; if (from >= 0) { Node *b = reinterpret_cast(p.begin()); Node *n = reinterpret_cast(p.at(from + 1)); while (n-- != b) { if (n->t() == t) return n - b; } } return -1; } template Q_OUTOFLINE_TEMPLATE bool QList::contains(const T &t) const { Node *b = reinterpret_cast(p.begin()); Node *i = reinterpret_cast(p.end()); while (i-- != b) if (i->t() == t) return true; return false; } template Q_OUTOFLINE_TEMPLATE int QList::count(const T &t) const { int c = 0; Node *b = reinterpret_cast(p.begin()); Node *i = reinterpret_cast(p.end()); while (i-- != b) if (i->t() == t) ++c; return c; } Q_DECLARE_SEQUENTIAL_ITERATOR(List) Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List) QT_END_NAMESPACE #endif // QLIST_H