summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qlist.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r--src/corelib/tools/qlist.h756
1 files changed, 748 insertions, 8 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 515fba6530..1c9a547395 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2019 Intel Corporation
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -40,18 +41,757 @@
#ifndef QLIST_H
#define QLIST_H
-#include <QtCore/qvector.h>
-#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qarraydatapointer.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qhashfunctions.h>
+#include <QtCore/qiterator.h>
+
+#include <functional>
+#include <limits>
+#include <initializer_list>
+#include <type_traits>
-#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+ template <typename V, typename U> int indexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> int lastIndexOf(const QList<V> &list, const U &u, int from);
+}
+
+template <typename T> struct QListSpecialMethods
+{
+protected:
+ ~QListSpecialMethods() = default;
+};
+template <> struct QListSpecialMethods<QByteArray>;
+template <> struct QListSpecialMethods<QString>;
+
+template <typename T>
+class QList
+#ifndef Q_QDOC
+ : public QListSpecialMethods<T>
+#endif
+{
+ typedef QTypedArrayData<T> Data;
+ typedef QArrayDataOps<T> DataOps;
+ typedef QArrayDataPointer<T> DataPointer;
+ class DisableRValueRefs {};
+
+ DataPointer d;
+
+ template <typename V, typename U> friend int QtPrivate::indexOf(const QList<V> &list, const U &u, int from);
+ template <typename V, typename U> friend int QtPrivate::lastIndexOf(const QList<V> &list, const U &u, int from);
+
+public:
+ typedef T 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 int size_type;
+ typedef qptrdiff difference_type;
+ typedef typename Data::iterator iterator;
+ typedef typename Data::const_iterator const_iterator;
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef typename DataPointer::parameter_type parameter_type;
+ using rvalue_ref = typename std::conditional<DataPointer::pass_parameter_by_value, DisableRValueRefs, T &&>::type;
+
+private:
+ void resize_internal(int i, Qt::Initialization);
+ bool isValidIterator(const_iterator i) const
+ {
+ const std::less<const T*> less = {};
+ return !less(d->end(), i) && !less(i, d->begin());
+ }
+public:
+ QList(DataPointer dd) noexcept
+ : d(dd)
+ {
+ }
+
+public:
+ constexpr inline QList() noexcept { }
+ explicit QList(int size)
+ : d(Data::allocate(size))
+ {
+ if (size)
+ d->appendInitialize(size);
+ }
+ QList(int size, const T &t)
+ : d(Data::allocate(size))
+ {
+ if (size)
+ d->copyAppend(size, t);
+ }
+
+ inline QList(const QList<T> &other) noexcept : d(other.d) {}
+ QList(QList<T> &&other) noexcept : d(std::move(other.d)) {}
+ inline QList(std::initializer_list<T> args)
+ : d(Data::allocate(args.size()))
+ {
+ if (args.size())
+ d->copyAppend(args.begin(), args.end());
+ }
+
+ ~QList() /*noexcept(std::is_nothrow_destructible<T>::value)*/ {}
+ QList<T> &operator=(const QList<T> &other) { d = other.d; return *this; }
+ QList &operator=(QList &&other) noexcept(std::is_nothrow_destructible<T>::value)
+ {
+ d = std::move(other.d);
+ return *this;
+ }
+ QList<T> &operator=(std::initializer_list<T> args)
+ {
+ d = DataPointer(Data::allocate(args.size()));
+ if (args.size())
+ d->copyAppend(args.begin(), args.end());
+ return *this;
+ }
+ template <typename InputIterator, QtPrivate::IfIsForwardIterator<InputIterator> = true>
+ QList(InputIterator i1, InputIterator i2)
+ : d(Data::allocate(std::distance(i1, i2)))
+ {
+ if (std::distance(i1, i2))
+ d->copyAppend(i1, i2);
+ }
+
+ template <typename InputIterator, QtPrivate::IfIsNotForwardIterator<InputIterator> = true>
+ QList(InputIterator i1, InputIterator i2)
+ : QList()
+ {
+ QtPrivate::reserveIfForwardIterator(this, i1, i2);
+ std::copy(i1, i2, std::back_inserter(*this));
+ }
+
+ void swap(QList<T> &other) noexcept { qSwap(d, other.d); }
+
+ friend bool operator==(const QList &l, const QList &r)
+ {
+ if (l.size() != r.size())
+ return false;
+ if (l.begin() == r.begin())
+ return true;
+
+ // do element-by-element comparison
+ return l.d->compare(l.begin(), r.begin(), l.size());
+ }
+ friend bool operator!=(const QList &l, const QList &r)
+ {
+ return !(l == r);
+ }
+
+ int size() const noexcept { return int(d->size); }
+ int count() const noexcept { return size(); }
+ int length() const noexcept { return size(); }
+
+ inline bool isEmpty() const noexcept { return d->size == 0; }
+
+ void resize(int size)
+ {
+ resize_internal(size, Qt::Uninitialized);
+ if (size > this->size())
+ d->appendInitialize(size);
+ }
+ void resize(int size, parameter_type c)
+ {
+ resize_internal(size, Qt::Uninitialized);
+ if (size > this->size())
+ d->copyAppend(size - this->size(), c);
+ }
+
+ inline int capacity() const { return int(d->constAllocatedCapacity()); }
+ void reserve(int size);
+ inline void squeeze();
+
+ void detach() { d.detach(); }
+ bool isDetached() const noexcept { return !d->isShared(); }
+
+ inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
+
+ pointer data() { detach(); return d->data(); }
+ const_pointer data() const noexcept { return d->data(); }
+ const_pointer constData() const noexcept { return d->data(); }
+ void clear() {
+ if (!size())
+ return;
+ if (d->needsDetach()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d.allocatedCapacity(), d->detachFlags()));
+ d.swap(detached);
+ } else {
+ d->truncate(0);
+ }
+ }
+
+ const_reference at(int i) const noexcept
+ {
+ Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::at", "index out of range");
+ return data()[i];
+ }
+ reference operator[](int i)
+ {
+ Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::operator[]", "index out of range");
+ detach();
+ return data()[i];
+ }
+ const_reference operator[](int i) const noexcept { return at(i); }
+ void append(const_reference t)
+ { append(const_iterator(std::addressof(t)), const_iterator(std::addressof(t)) + 1); }
+ void append(const_iterator i1, const_iterator i2);
+ void append(rvalue_ref t) { emplaceBack(std::move(t)); }
+ void append(const QList<T> &l) { append(l.constBegin(), l.constEnd()); }
+ void prepend(rvalue_ref t);
+ void prepend(const T &t);
+
+ template <typename ...Args>
+ reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward<Args>(args)...); }
+
+ iterator insert(int i, parameter_type t)
+ { return insert(i, 1, t); }
+ iterator insert(int i, int n, parameter_type t);
+ iterator insert(const_iterator before, parameter_type t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
+ return insert(before, 1, t);
+ }
+ iterator insert(const_iterator before, int n, parameter_type t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
+ return insert(std::distance(constBegin(), before), n, t);
+ }
+ iterator insert(const_iterator before, rvalue_ref t)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QList::insert", "The specified iterator argument 'before' is invalid");
+ return insert(std::distance(constBegin(), before), std::move(t));
+ }
+ iterator insert(int i, rvalue_ref t) { return emplace(i, std::move(t)); }
+
+ template <typename ...Args>
+ iterator emplace(const_iterator before, Args&&... args)
+ {
+ Q_ASSERT_X(isValidIterator(before), "QList::emplace", "The specified iterator argument 'before' is invalid");
+ return emplace(std::distance(constBegin(), before), std::forward<Args>(args)...);
+ }
+
+ template <typename ...Args>
+ iterator emplace(int i, Args&&... args);
+#if 0
+ template< class InputIt >
+ iterator insert( const_iterator pos, InputIt first, InputIt last );
+ iterator insert( const_iterator pos, std::initializer_list<T> ilist );
+#endif
+ void replace(int i, const T &t)
+ {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
+ const T copy(t);
+ data()[i] = copy;
+ }
+ void replace(int i, rvalue_ref t)
+ {
+ Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
+ const T copy(std::move(t));
+ data()[i] = std::move(copy);
+ }
+
+ void remove(int i, int n = 1);
+ void removeFirst() { Q_ASSERT(!isEmpty()); remove(0); }
+ void removeLast() { Q_ASSERT(!isEmpty()); remove(size() - 1); }
+ value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); remove(0); return v; }
+ value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); remove(size() - 1); return v; }
+
+ QList<T> &fill(parameter_type t, int size = -1);
+
+ int indexOf(const T &t, int from = 0) const noexcept;
+ int lastIndexOf(const T &t, int from = -1) const noexcept;
+ bool contains(const T &t) const noexcept
+ {
+ return indexOf(t) != -1;
+ }
+ int count(const T &t) const noexcept
+ {
+ return int(std::count(&*cbegin(), &*cend(), t));
+ }
+
+ // QList compatibility
+ void removeAt(int i) { remove(i); }
+ int removeAll(const T &t)
+ {
+ const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
+ if (cit == ce)
+ return 0;
+ int index = cit - this->cbegin();
+ // next operation detaches, so ce, cit, t may become invalidated:
+ const T tCopy = t;
+ const iterator e = end(), it = std::remove(begin() + index, e, tCopy);
+ const int result = std::distance(it, e);
+ erase(it, e);
+ return result;
+ }
+ bool removeOne(const T &t)
+ {
+ const int i = indexOf(t);
+ if (i < 0)
+ return false;
+ remove(i);
+ return true;
+ }
+ T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; }
+ void move(int from, int to)
+ {
+ Q_ASSERT_X(from >= 0 && from < size(), "QList::move(int,int)", "'from' is out-of-range");
+ Q_ASSERT_X(to >= 0 && to < size(), "QList::move(int,int)", "'to' is out-of-range");
+ if (from == to) // don't detach when no-op
+ return;
+ detach();
+ T * const b = d->begin();
+ if (from < to)
+ std::rotate(b + from, b + from + 1, b + to + 1);
+ else
+ std::rotate(b + to, b + from, b + from + 1);
+ }
+
+ // STL-style
+ iterator begin() { detach(); return d->begin(); }
+ iterator end() { detach(); return d->end(); }
+
+ const_iterator begin() const noexcept { return d->constBegin(); }
+ const_iterator end() const noexcept { return d->constEnd(); }
+ const_iterator cbegin() const noexcept { return d->constBegin(); }
+ const_iterator cend() const noexcept { return d->constEnd(); }
+ const_iterator constBegin() const noexcept { return d->constBegin(); }
+ const_iterator constEnd() const noexcept { return d->constEnd(); }
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
+
+ iterator erase(const_iterator begin, const_iterator end);
+ inline iterator erase(const_iterator pos) { return erase(pos, pos+1); }
+
+ // more Qt
+ inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T &constFirst() const { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline const T &constLast() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
+ inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
+ QList<T> mid(int pos, int len = -1) const;
+
+ T value(int i) const { return value(i, T()); }
+ T value(int i, const T &defaultValue) const;
+
+ void swapItemsAt(int i, int j) {
+ Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
+ "QList<T>::swap", "index out of range");
+ detach();
+ qSwap(d->begin()[i], d->begin()[j]);
+ }
+
+ // STL compatibility
+ inline void push_back(const T &t) { append(t); }
+ void push_back(rvalue_ref t) { append(std::move(t)); }
+ void push_front(rvalue_ref t) { prepend(std::move(t)); }
+ inline void push_front(const T &t) { prepend(t); }
+ void pop_back() { removeLast(); }
+ void pop_front() { removeFirst(); }
+
+ template <typename ...Args>
+ reference emplace_back(Args&&... args) { return emplaceBack(std::forward<Args>(args)...); }
+
+ inline bool empty() const
+ { return d->size == 0; }
+ inline reference front() { return first(); }
+ inline const_reference front() const { return first(); }
+ inline reference back() { return last(); }
+ inline const_reference back() const { return last(); }
+ void shrink_to_fit() { squeeze(); }
+
+ // comfort
+ QList<T> &operator+=(const QList<T> &l) { append(l.cbegin(), l.cend()); return *this; }
+ inline QList<T> operator+(const QList<T> &l) const
+ { QList n = *this; n += l; return n; }
+ inline QList<T> &operator+=(const T &t)
+ { append(t); return *this; }
+ inline QList<T> &operator<< (const T &t)
+ { append(t); return *this; }
+ inline QList<T> &operator<<(const QList<T> &l)
+ { *this += l; return *this; }
+ inline QList<T> &operator+=(rvalue_ref t)
+ { append(std::move(t)); return *this; }
+ inline QList<T> &operator<<(rvalue_ref t)
+ { append(std::move(t)); return *this; }
+
+ // Consider deprecating in 6.4 or later
+ static QList<T> fromList(const QList<T> &list) { return list; }
+ QList<T> toList() const { return *this; }
+
+ static inline QList<T> fromVector(const QList<T> &vector) { return vector; }
+ inline QList<T> toVector() const { return *this; }
+};
+
+#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606
+template <typename InputIterator,
+ typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
+ QtPrivate::IfIsInputIterator<InputIterator> = true>
+QList(InputIterator, InputIterator) -> QList<ValueType>;
+#endif
+
+template <typename T>
+inline void QList<T>::resize_internal(int newSize, Qt::Initialization)
+{
+ Q_ASSERT(newSize >= 0);
+
+ if (d->needsDetach() || newSize > capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags()));
+ if (size() && newSize) {
+ detached->copyAppend(constBegin(), constBegin() + qMin(newSize, size()));
+ }
+ d.swap(detached);
+ }
+
+ if (newSize < size())
+ d->truncate(newSize);
+}
+
+template <typename T>
+void QList<T>::reserve(int asize)
+{
+ // capacity() == 0 for immutable data, so this will force a detaching below
+ if (asize <= capacity()) {
+ if (d->flags() & Data::CapacityReserved)
+ return; // already reserved, don't shrink
+ if (!d->isShared()) {
+ // accept current allocation, don't shrink
+ d->flags() |= Data::CapacityReserved;
+ return;
+ }
+ }
+
+ DataPointer detached(Data::allocate(qMax(asize, size()),
+ d->detachFlags() | Data::CapacityReserved));
+ detached->copyAppend(constBegin(), constEnd());
+ d.swap(detached);
+}
+
+template <typename T>
+inline void QList<T>::squeeze()
+{
+ if (d->needsDetach() || size() != capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(size(), d->detachFlags() & ~Data::CapacityReserved));
+ if (size()) {
+ detached->copyAppend(constBegin(), constEnd());
+ }
+ d.swap(detached);
+ }
+}
+
+template <typename T>
+inline void QList<T>::remove(int i, int n)
+{
+ Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size), "QList::remove", "index out of range");
+ Q_ASSERT_X(n >= 0, "QList::remove", "invalid count");
+
+ if (n == 0)
+ return;
+
+ const size_t newSize = size() - n;
+ if (d->needsDetach() ||
+ ((d->flags() & Data::CapacityReserved) == 0
+ && newSize < d->allocatedCapacity()/2)) {
+ // allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags() & ~(Data::GrowsBackwards | Data::GrowsForward)));
+ const_iterator where = constBegin() + i;
+ if (newSize) {
+ detached->copyAppend(constBegin(), where);
+ detached->copyAppend(where + n, constEnd());
+ }
+ d.swap(detached);
+ } else {
+ // we're detached and we can just move data around
+ d->erase(d->begin() + i, d->begin() + i + n);
+ }
+}
+
+template <typename T>
+inline void QList<T>::prepend(const T &t)
+{ insert(0, 1, t); }
+template <typename T>
+void QList<T>::prepend(rvalue_ref t)
+{ insert(0, std::move(t)); }
+
template<typename T>
-using QMutableListIterator = QMutableVectorIterator<T>;
-template<typename T>
-using QListIterator = QVectorIterator<T>;
-QT_END_NAMESPACE
+inline T QList<T>::value(int i, const T &defaultValue) const
+{
+ return size_t(i) < size_t(d->size) ? at(i) : defaultValue;
+}
+
+template <typename T>
+inline void QList<T>::append(const_iterator i1, const_iterator i2)
+{
+ if (i1 == i2)
+ return;
+ const size_t newSize = size() + std::distance(i1, i2);
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags() | Data::GrowsForward));
+ detached->copyAppend(constBegin(), constEnd());
+ detached->copyAppend(i1, i2);
+ d.swap(detached);
+ } else {
+ // we're detached and we can just move data around
+ d->copyAppend(i1, i2);
+ }
+}
+
+template <typename T>
+inline typename QList<T>::iterator
+QList<T>::insert(int i, int n, parameter_type t)
+{
+ Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range");
+
+ // we don't have a quick exit for n == 0
+ // it's not worth wasting CPU cycles for that
+
+ const size_t newSize = size() + n;
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
+ if (size_t(i) <= newSize / 4)
+ flags |= Data::GrowsBackwards;
+
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
+ const_iterator where = constBegin() + i;
+ detached->copyAppend(constBegin(), where);
+ detached->copyAppend(n, t);
+ detached->copyAppend(where, constEnd());
+ d.swap(detached);
+ } else {
+ // we're detached and we can just move data around
+ if (i == size()) {
+ d->copyAppend(n, t);
+ } else {
+ T copy(t);
+ d->insert(d.begin() + i, n, copy);
+ }
+ }
+ return d.begin() + i;
+}
+
+template <typename T>
+template <typename ...Args>
+typename QList<T>::iterator
+QList<T>::emplace(int i, Args&&... args)
+{
+ Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
+
+ const size_t newSize = size() + 1;
+ if (d->needsDetach() || newSize > d->allocatedCapacity()) {
+ typename Data::ArrayOptions flags = d->detachFlags() | Data::GrowsForward;
+ if (size_t(i) <= newSize / 4)
+ flags |= Data::GrowsBackwards;
+
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize), flags));
+ const_iterator where = constBegin() + i;
+
+ // First, create an element to handle cases, when a user moves
+ // the element from a container to the same container
+ detached->createInPlace(detached.begin() + i, std::forward<Args>(args)...);
+
+ // Then, put the first part of the elements to the new location
+ detached->copyAppend(constBegin(), where);
+
+ // After that, increase the actual size, because we created
+ // one extra element
+ ++detached.size;
+
+ // Finally, put the rest of the elements to the new location
+ detached->copyAppend(where, constEnd());
+
+ d.swap(detached);
+ } else {
+ d->emplace(d.begin() + i, std::forward<Args>(args)...);
+ }
+ return d.begin() + i;
+}
+
+template <typename T>
+typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterator aend)
+{
+ Q_ASSERT_X(isValidIterator(abegin), "QList::erase", "The specified iterator argument 'abegin' is invalid");
+ Q_ASSERT_X(isValidIterator(aend), "QList::erase", "The specified iterator argument 'aend' is invalid");
+ Q_ASSERT(aend >= abegin);
+
+ int i = std::distance(d.constBegin(), abegin);
+ int n = std::distance(abegin, aend);
+ remove(i, n);
+
+ return d.begin() + i;
+}
+
+template <typename T>
+inline QList<T> &QList<T>::fill(parameter_type t, int newSize)
+{
+ if (newSize == -1)
+ newSize = size();
+ if (d->needsDetach() || newSize > capacity()) {
+ // must allocate memory
+ DataPointer detached(Data::allocate(d->detachCapacity(newSize),
+ d->detachFlags()));
+ detached->copyAppend(newSize, t);
+ d.swap(detached);
+ } else {
+ // we're detached
+ const T copy(t);
+ d->assign(d.begin(), d.begin() + qMin(size(), newSize), t);
+ if (newSize > size())
+ d->copyAppend(newSize - size(), copy);
+ }
+ return *this;
+}
+
+namespace QtPrivate {
+template <typename T, typename U>
+int indexOf(const QList<T> &vector, const U &u, int from)
+{
+ if (from < 0)
+ from = qMax(from + vector.size(), 0);
+ if (from < vector.size()) {
+ auto n = vector.begin() + from - 1;
+ auto e = vector.end();
+ while (++n != e)
+ if (*n == u)
+ return int(n - vector.begin());
+ }
+ return -1;
+}
+
+template <typename T, typename U>
+int lastIndexOf(const QList<T> &vector, const U &u, int from)
+{
+ if (from < 0)
+ from += vector.d->size;
+ else if (from >= vector.size())
+ from = vector.size() - 1;
+ if (from >= 0) {
+ auto b = vector.begin();
+ auto n = vector.begin() + from + 1;
+ while (n != b) {
+ if (*--n == u)
+ return int(n - b);
+ }
+ }
+ return -1;
+}
+}
+
+template <typename T>
+int QList<T>::indexOf(const T &t, int from) const noexcept
+{
+ return QtPrivate::indexOf<T, T>(*this, t, from);
+}
+
+template <typename T>
+int QList<T>::lastIndexOf(const T &t, int from) const noexcept
+{
+ return QtPrivate::lastIndexOf(*this, t, from);
+}
+
+template <typename T>
+inline QList<T> QList<T>::mid(int pos, int len) const
+{
+ qsizetype p = pos;
+ qsizetype l = len;
+ using namespace QtPrivate;
+ switch (QContainerImplHelper::mid(d.size, &p, &l)) {
+ case QContainerImplHelper::Null:
+ case QContainerImplHelper::Empty:
+ return QList();
+ case QContainerImplHelper::Full:
+ return *this;
+ case QContainerImplHelper::Subset:
+ break;
+ }
+
+ // Allocate memory
+ DataPointer copied(Data::allocate(l));
+ copied->copyAppend(constBegin() + p, constBegin() + p + l);
+ return copied;
+}
+
+Q_DECLARE_SEQUENTIAL_ITERATOR(List)
+Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
+
+template <typename T>
+size_t qHash(const QList<T> &key, size_t seed = 0)
+ noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
+{
+ return qHashRange(key.cbegin(), key.cend(), seed);
+}
+
+template <typename T>
+auto operator<(const QList<T> &lhs, const QList<T> &rhs)
+ noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end())))
+ -> decltype(std::declval<T>() < std::declval<T>())
+{
+ return std::lexicographical_compare(lhs.begin(), lhs.end(),
+ rhs.begin(), rhs.end());
+}
+
+template <typename T>
+auto operator>(const QList<T> &lhs, const QList<T> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ -> decltype(lhs < rhs)
+{
+ return rhs < lhs;
+}
+
+template <typename T>
+auto operator<=(const QList<T> &lhs, const QList<T> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ -> decltype(lhs < rhs)
+{
+ return !(lhs > rhs);
+}
+
+template <typename T>
+auto operator>=(const QList<T> &lhs, const QList<T> &rhs)
+ noexcept(noexcept(lhs < rhs))
+ -> decltype(lhs < rhs)
+{
+ return !(lhs < rhs);
+}
+
+/*
+ ### Qt 5:
+ ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
+ ### Qt exports QPolygon and QPolygonF that inherit QList<QPoint> and
+ ### QList<QPointF> respectively.
+*/
+
+#if defined(Q_CC_MSVC) && !defined(QT_BUILD_CORE_LIB)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtCore/qpoint.h>
+QT_END_INCLUDE_NAMESPACE
+extern template class Q_CORE_EXPORT QList<QPointF>;
+extern template class Q_CORE_EXPORT QList<QPoint>;
#endif
+QList<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
+
+QT_END_NAMESPACE
+
#include <QtCore/qbytearraylist.h>
#include <QtCore/qstringlist.h>