Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qlist.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // Copyright (C) 2019 Intel Corporation
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QLIST_H
0006 #define QLIST_H
0007 
0008 #include <QtCore/qarraydatapointer.h>
0009 #include <QtCore/qnamespace.h>
0010 #include <QtCore/qhashfunctions.h>
0011 #include <QtCore/qiterator.h>
0012 #include <QtCore/qcontainertools_impl.h>
0013 
0014 #include <functional>
0015 #include <limits>
0016 #include <initializer_list>
0017 #include <type_traits>
0018 
0019 class tst_QList;
0020 
0021 QT_BEGIN_NAMESPACE
0022 
0023 namespace QtPrivate {
0024    template <typename V, typename U> qsizetype indexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
0025    template <typename V, typename U> qsizetype lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
0026 }
0027 
0028 template <typename T> struct QListSpecialMethodsBase
0029 {
0030 protected:
0031     ~QListSpecialMethodsBase() = default;
0032 
0033     using Self = QList<T>;
0034     Self *self() { return static_cast<Self *>(this); }
0035     const Self *self() const { return static_cast<const Self *>(this); }
0036 
0037 public:
0038     template <typename AT = T>
0039     qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
0040     template <typename AT = T>
0041     qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
0042 
0043     template <typename AT = T>
0044     bool contains(const AT &t) const noexcept
0045     {
0046         return self()->indexOf(t) != -1;
0047     }
0048 };
0049 template <typename T> struct QListSpecialMethods : QListSpecialMethodsBase<T>
0050 {
0051 protected:
0052     ~QListSpecialMethods() = default;
0053 public:
0054     using QListSpecialMethodsBase<T>::indexOf;
0055     using QListSpecialMethodsBase<T>::lastIndexOf;
0056     using QListSpecialMethodsBase<T>::contains;
0057 };
0058 template <> struct QListSpecialMethods<QByteArray>;
0059 template <> struct QListSpecialMethods<QString>;
0060 
0061 #if !defined(QT_STRICT_QLIST_ITERATORS) && (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)) && !defined(Q_OS_WIN)
0062 #define QT_STRICT_QLIST_ITERATORS
0063 #endif
0064 
0065 #ifdef Q_QDOC // define QVector for QDoc
0066 template<typename T> class QVector : public QList<T> {};
0067 #endif
0068 
0069 template <typename T>
0070 class QList
0071 #ifndef Q_QDOC
0072     : public QListSpecialMethods<T>
0073 #endif
0074 {
0075     using Data = QTypedArrayData<T>;
0076     using DataOps = QArrayDataOps<T>;
0077     using DataPointer = QArrayDataPointer<T>;
0078     class DisableRValueRefs {};
0079 
0080     friend class ::tst_QList;
0081 
0082     DataPointer d;
0083 
0084     template <typename V, typename U> friend qsizetype QtPrivate::indexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
0085     template <typename V, typename U> friend qsizetype QtPrivate::lastIndexOf(const QList<V> &list, const U &u, qsizetype from) noexcept;
0086     // This alias prevents the QtPrivate namespace from being exposed into the docs.
0087     template <typename InputIterator>
0088     using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>;
0089 
0090 public:
0091     using Type = T;
0092     using value_type = T;
0093     using pointer = T *;
0094     using const_pointer = const T *;
0095     using reference = T &;
0096     using const_reference = const T &;
0097     using size_type = qsizetype;
0098     using difference_type = qptrdiff;
0099 #ifndef Q_QDOC
0100     using parameter_type = typename DataPointer::parameter_type;
0101     using rvalue_ref = typename std::conditional<DataPointer::pass_parameter_by_value, DisableRValueRefs, T &&>::type;
0102 #else  // simplified aliases for QDoc
0103     using parameter_type = const T &;
0104     using rvalue_ref = T &&;
0105 #endif
0106 
0107     class const_iterator;
0108     class iterator {
0109         friend class QList<T>;
0110         friend class const_iterator;
0111         T *i = nullptr;
0112 #ifdef QT_STRICT_QLIST_ITERATORS
0113         inline constexpr explicit iterator(T *n) : i(n) {}
0114 #endif
0115 
0116     public:
0117         using difference_type = qsizetype;
0118         using value_type = T;
0119 #ifdef QT_COMPILER_HAS_LWG3346
0120         using iterator_concept = std::contiguous_iterator_tag;
0121         using element_type = value_type;
0122 #endif
0123         using iterator_category = std::random_access_iterator_tag;
0124         using pointer = T *;
0125         using reference = T &;
0126 
0127         inline constexpr iterator() = default;
0128 #ifndef QT_STRICT_QLIST_ITERATORS
0129         inline constexpr explicit iterator(T *n) : i(n) {}
0130 #endif
0131         inline T &operator*() const { return *i; }
0132         inline T *operator->() const { return i; }
0133         inline T &operator[](qsizetype j) const { return *(i + j); }
0134         inline constexpr bool operator==(iterator o) const { return i == o.i; }
0135         inline constexpr bool operator!=(iterator o) const { return i != o.i; }
0136         inline constexpr bool operator<(iterator other) const { return i < other.i; }
0137         inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
0138         inline constexpr bool operator>(iterator other) const { return i > other.i; }
0139         inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
0140         inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
0141         inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
0142         inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
0143         inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
0144         inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
0145         inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
0146         inline constexpr bool operator==(pointer p) const { return i == p; }
0147         inline constexpr bool operator!=(pointer p) const { return i != p; }
0148         inline iterator &operator++() { ++i; return *this; }
0149         inline iterator operator++(int) { auto copy = *this; ++*this; return copy; }
0150         inline iterator &operator--() { --i; return *this; }
0151         inline iterator operator--(int) { auto copy = *this; --*this; return copy; }
0152         inline qsizetype operator-(iterator j) const { return i - j.i; }
0153 #if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
0154         QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
0155                                     "the implicit conversion between a QList/QVector::iterator "
0156                                     "and a raw pointer")
0157         inline operator T*() const { return i; }
0158 
0159         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
0160         &operator+=(Int j) { i+=j; return *this; }
0161         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
0162         &operator-=(Int j) { i-=j; return *this; }
0163         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
0164         operator+(Int j) const { return iterator(i+j); }
0165         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, iterator>
0166         operator-(Int j) const { return iterator(i-j); }
0167         template <typename Int> friend std::enable_if_t<std::is_integral_v<Int>, iterator>
0168         operator+(Int j, iterator k) { return k + j; }
0169 #else
0170         inline iterator &operator+=(qsizetype j) { i += j; return *this; }
0171         inline iterator &operator-=(qsizetype j) { i -= j; return *this; }
0172         inline iterator operator+(qsizetype j) const { return iterator(i + j); }
0173         inline iterator operator-(qsizetype j) const { return iterator(i - j); }
0174         friend inline iterator operator+(qsizetype j, iterator k) { return k + j; }
0175 #endif
0176     };
0177 
0178     class const_iterator {
0179         friend class QList<T>;
0180         friend class iterator;
0181         const T *i = nullptr;
0182 #ifdef QT_STRICT_QLIST_ITERATORS
0183         inline constexpr explicit const_iterator(const T *n) : i(n) {}
0184 #endif
0185 
0186     public:
0187         using difference_type = qsizetype;
0188         using value_type = T;
0189 #ifdef QT_COMPILER_HAS_LWG3346
0190         using iterator_concept = std::contiguous_iterator_tag;
0191         using element_type = const value_type;
0192 #endif
0193         using iterator_category = std::random_access_iterator_tag;
0194         using pointer = const T *;
0195         using reference = const T &;
0196 
0197         inline constexpr const_iterator() = default;
0198 #ifndef QT_STRICT_QLIST_ITERATORS
0199         inline constexpr explicit const_iterator(const T *n) : i(n) {}
0200 #endif
0201         inline constexpr const_iterator(iterator o): i(o.i) {}
0202         inline const T &operator*() const { return *i; }
0203         inline const T *operator->() const { return i; }
0204         inline const T &operator[](qsizetype j) const { return *(i + j); }
0205         inline constexpr bool operator==(const_iterator o) const { return i == o.i; }
0206         inline constexpr bool operator!=(const_iterator o) const { return i != o.i; }
0207         inline constexpr bool operator<(const_iterator other) const { return i < other.i; }
0208         inline constexpr bool operator<=(const_iterator other) const { return i <= other.i; }
0209         inline constexpr bool operator>(const_iterator other) const { return i > other.i; }
0210         inline constexpr bool operator>=(const_iterator other) const { return i >= other.i; }
0211         inline constexpr bool operator==(iterator o) const { return i == o.i; }
0212         inline constexpr bool operator!=(iterator o) const { return i != o.i; }
0213         inline constexpr bool operator<(iterator other) const { return i < other.i; }
0214         inline constexpr bool operator<=(iterator other) const { return i <= other.i; }
0215         inline constexpr bool operator>(iterator other) const { return i > other.i; }
0216         inline constexpr bool operator>=(iterator other) const { return i >= other.i; }
0217         inline constexpr bool operator==(pointer p) const { return i == p; }
0218         inline constexpr bool operator!=(pointer p) const { return i != p; }
0219         inline const_iterator &operator++() { ++i; return *this; }
0220         inline const_iterator operator++(int) { auto copy = *this; ++*this; return copy; }
0221         inline const_iterator &operator--() { --i; return *this; }
0222         inline const_iterator operator--(int) { auto copy = *this; --*this; return copy; }
0223         inline qsizetype operator-(const_iterator j) const { return i - j.i; }
0224 #if QT_DEPRECATED_SINCE(6, 3) && !defined(QT_STRICT_QLIST_ITERATORS)
0225         QT_DEPRECATED_VERSION_X_6_3("Use operator* or operator-> rather than relying on "
0226                                     "the implicit conversion between a QList/QVector::const_iterator "
0227                                     "and a raw pointer")
0228         inline operator const T*() const { return i; }
0229 
0230         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
0231         &operator+=(Int j) { i+=j; return *this; }
0232         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
0233         &operator-=(Int j) { i-=j; return *this; }
0234         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
0235         operator+(Int j) const { return const_iterator(i+j); }
0236         template <typename Int> std::enable_if_t<std::is_integral_v<Int>, const_iterator>
0237         operator-(Int j) const { return const_iterator(i-j); }
0238         template <typename Int> friend std::enable_if_t<std::is_integral_v<Int>, const_iterator>
0239         operator+(Int j, const_iterator k) { return k + j; }
0240 #else
0241         inline const_iterator &operator+=(qsizetype j) { i += j; return *this; }
0242         inline const_iterator &operator-=(qsizetype j) { i -= j; return *this; }
0243         inline const_iterator operator+(qsizetype j) const { return const_iterator(i + j); }
0244         inline const_iterator operator-(qsizetype j) const { return const_iterator(i - j); }
0245         friend inline const_iterator operator+(qsizetype j, const_iterator k) { return k + j; }
0246 #endif
0247     };
0248     using Iterator = iterator;
0249     using ConstIterator = const_iterator;
0250     using reverse_iterator = std::reverse_iterator<iterator>;
0251     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
0252 
0253 private:
0254     void resize_internal(qsizetype i);
0255     bool isValidIterator(const_iterator i) const
0256     {
0257         const std::less<const T*> less = {};
0258         return !less(d->end(), i.i) && !less(i.i, d->begin());
0259     }
0260 
0261     void verify([[maybe_unused]] qsizetype pos = 0, [[maybe_unused]] qsizetype n = 1) const
0262     {
0263         Q_ASSERT(pos >= 0);
0264         Q_ASSERT(pos <= size());
0265         Q_ASSERT(n >= 0);
0266         Q_ASSERT(n <= size() - pos);
0267     }
0268 public:
0269     QList(DataPointer dd) noexcept
0270         : d(dd)
0271     {
0272     }
0273 
0274 public:
0275     QList() = default;
0276     explicit QList(qsizetype size)
0277         : d(size)
0278     {
0279         if (size)
0280             d->appendInitialize(size);
0281     }
0282     QList(qsizetype size, parameter_type t)
0283         : d(size)
0284     {
0285         if (size)
0286             d->copyAppend(size, t);
0287     }
0288 
0289     inline QList(std::initializer_list<T> args)
0290         : d(qsizetype(args.size()))
0291     {
0292         if (args.size())
0293             d->copyAppend(args.begin(), args.end());
0294     }
0295 
0296     QList<T> &operator=(std::initializer_list<T> args)
0297     {
0298         return assign(args);
0299     }
0300 
0301     template <typename InputIterator, if_input_iterator<InputIterator> = true>
0302     QList(InputIterator i1, InputIterator i2)
0303     {
0304         if constexpr (!std::is_convertible_v<typename std::iterator_traits<InputIterator>::iterator_category, std::forward_iterator_tag>) {
0305             std::copy(i1, i2, std::back_inserter(*this));
0306         } else {
0307             const auto distance = std::distance(i1, i2);
0308             if (distance) {
0309                 d = DataPointer(qsizetype(distance));
0310                 // appendIteratorRange can deal with contiguous iterators on its own,
0311                 // this is an optimization for C++17 code.
0312                 if constexpr (std::is_same_v<std::decay_t<InputIterator>, iterator> ||
0313                               std::is_same_v<std::decay_t<InputIterator>, const_iterator>) {
0314                     d->copyAppend(i1.i, i2.i);
0315                 } else {
0316                     d->appendIteratorRange(i1, i2);
0317                }
0318             }
0319         }
0320     }
0321 
0322     // This constructor is here for compatibility with QStringList in Qt 5, that has a QStringList(const QString &) constructor
0323     template<typename String, typename = std::enable_if_t<std::is_same_v<T, QString> && std::is_convertible_v<String, QString>>>
0324     inline explicit QList(const String &str)
0325     { append(str); }
0326 
0327     // compiler-generated special member functions are fine!
0328 
0329     void swap(QList &other) noexcept { d.swap(other.d); }
0330 
0331 #ifndef Q_QDOC
0332     template <typename U = T>
0333     QTypeTraits::compare_eq_result_container<QList, U> operator==(const QList &other) const
0334     {
0335         if (size() != other.size())
0336             return false;
0337         if (begin() == other.begin())
0338             return true;
0339 
0340         // do element-by-element comparison
0341         return d->compare(data(), other.data(), size());
0342     }
0343     template <typename U = T>
0344     QTypeTraits::compare_eq_result_container<QList, U> operator!=(const QList &other) const
0345     {
0346         return !(*this == other);
0347     }
0348 
0349     template <typename U = T>
0350     QTypeTraits::compare_lt_result_container<QList, U> operator<(const QList &other) const
0351         noexcept(noexcept(std::lexicographical_compare<typename QList<U>::const_iterator,
0352                                                        typename QList::const_iterator>(
0353                             std::declval<QList<U>>().begin(), std::declval<QList<U>>().end(),
0354                             other.begin(), other.end())))
0355     {
0356         return std::lexicographical_compare(begin(), end(),
0357                                             other.begin(), other.end());
0358     }
0359 
0360     template <typename U = T>
0361     QTypeTraits::compare_lt_result_container<QList, U> operator>(const QList &other) const
0362         noexcept(noexcept(other < std::declval<QList<U>>()))
0363     {
0364         return other < *this;
0365     }
0366 
0367     template <typename U = T>
0368     QTypeTraits::compare_lt_result_container<QList, U> operator<=(const QList &other) const
0369         noexcept(noexcept(other < std::declval<QList<U>>()))
0370     {
0371         return !(other < *this);
0372     }
0373 
0374     template <typename U = T>
0375     QTypeTraits::compare_lt_result_container<QList, U> operator>=(const QList &other) const
0376         noexcept(noexcept(std::declval<QList<U>>() < other))
0377     {
0378         return !(*this < other);
0379     }
0380 #else
0381     bool operator==(const QList &other) const;
0382     bool operator!=(const QList &other) const;
0383     bool operator<(const QList &other) const;
0384     bool operator>(const QList &other) const;
0385     bool operator<=(const QList &other) const;
0386     bool operator>=(const QList &other) const;
0387 #endif // Q_QDOC
0388 
0389     qsizetype size() const noexcept { return d->size; }
0390     qsizetype count() const noexcept { return size(); }
0391     qsizetype length() const noexcept { return size(); }
0392 
0393     inline bool isEmpty() const noexcept { return d->size == 0; }
0394 
0395     void resize(qsizetype size)
0396     {
0397         resize_internal(size);
0398         if (size > this->size())
0399             d->appendInitialize(size);
0400     }
0401     void resize(qsizetype size, parameter_type c)
0402     {
0403         resize_internal(size);
0404         if (size > this->size())
0405             d->copyAppend(size - this->size(), c);
0406     }
0407 
0408     inline qsizetype capacity() const { return qsizetype(d->constAllocatedCapacity()); }
0409     void reserve(qsizetype size);
0410     inline void squeeze();
0411 
0412     void detach() { d.detach(); }
0413     bool isDetached() const noexcept { return !d->isShared(); }
0414 
0415     inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
0416 
0417     pointer data() { detach(); return d->data(); }
0418     const_pointer data() const noexcept { return d->data(); }
0419     const_pointer constData() const noexcept { return d->data(); }
0420     void clear() {
0421         if (!size())
0422             return;
0423         if (d->needsDetach()) {
0424             // must allocate memory
0425             DataPointer detached(d.allocatedCapacity());
0426             d.swap(detached);
0427         } else {
0428             d->truncate(0);
0429         }
0430     }
0431 
0432     const_reference at(qsizetype i) const noexcept
0433     {
0434         Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::at", "index out of range");
0435         return data()[i];
0436     }
0437     reference operator[](qsizetype i)
0438     {
0439         Q_ASSERT_X(size_t(i) < size_t(d->size), "QList::operator[]", "index out of range");
0440         // don't detach() here, we detach in data below:
0441         return data()[i];
0442     }
0443     const_reference operator[](qsizetype i) const noexcept { return at(i); }
0444     void append(parameter_type t) { emplaceBack(t); }
0445     void append(const_iterator i1, const_iterator i2);
0446     void append(rvalue_ref t)
0447     {
0448         if constexpr (DataPointer::pass_parameter_by_value) {
0449             Q_UNUSED(t);
0450         } else {
0451             emplaceBack(std::move(t));
0452         }
0453     }
0454     void append(const QList<T> &l)
0455     {
0456         append(l.constBegin(), l.constEnd());
0457     }
0458     void append(QList<T> &&l);
0459     void prepend(rvalue_ref t) {
0460         if constexpr (DataPointer::pass_parameter_by_value) {
0461             Q_UNUSED(t);
0462         } else {
0463             emplaceFront(std::move(t));
0464         }
0465     }
0466     void prepend(parameter_type t) { emplaceFront(t); }
0467 
0468     template<typename... Args>
0469     inline reference emplaceBack(Args &&... args);
0470 
0471     template <typename ...Args>
0472     inline reference emplaceFront(Args&&... args);
0473 
0474     iterator insert(qsizetype i, parameter_type t)
0475     { return emplace(i, t); }
0476     iterator insert(qsizetype i, qsizetype n, parameter_type t);
0477     iterator insert(const_iterator before, parameter_type t)
0478     {
0479         Q_ASSERT_X(isValidIterator(before),  "QList::insert", "The specified iterator argument 'before' is invalid");
0480         return insert(before, 1, t);
0481     }
0482     iterator insert(const_iterator before, qsizetype n, parameter_type t)
0483     {
0484         Q_ASSERT_X(isValidIterator(before),  "QList::insert", "The specified iterator argument 'before' is invalid");
0485         return insert(std::distance(constBegin(), before), n, t);
0486     }
0487     iterator insert(const_iterator before, rvalue_ref t)
0488     {
0489         Q_ASSERT_X(isValidIterator(before),  "QList::insert", "The specified iterator argument 'before' is invalid");
0490         return insert(std::distance(constBegin(), before), std::move(t));
0491     }
0492     iterator insert(qsizetype i, rvalue_ref t) {
0493         if constexpr (DataPointer::pass_parameter_by_value) {
0494             Q_UNUSED(i);
0495             Q_UNUSED(t);
0496             return end();
0497         } else {
0498             return emplace(i, std::move(t));
0499         }
0500     }
0501 
0502     QList &assign(qsizetype n, parameter_type t)
0503     {
0504         Q_ASSERT(n >= 0);
0505         return fill(t, n);
0506     }
0507 
0508     template <typename InputIterator, if_input_iterator<InputIterator> = true>
0509     QList &assign(InputIterator first, InputIterator last)
0510     { d.assign(first, last); return *this; }
0511 
0512     QList &assign(std::initializer_list<T> l)
0513     { return assign(l.begin(), l.end()); }
0514 
0515     template <typename ...Args>
0516     iterator emplace(const_iterator before, Args&&... args)
0517     {
0518         Q_ASSERT_X(isValidIterator(before),  "QList::emplace", "The specified iterator argument 'before' is invalid");
0519         return emplace(std::distance(constBegin(), before), std::forward<Args>(args)...);
0520     }
0521 
0522     template <typename ...Args>
0523     iterator emplace(qsizetype i, Args&&... args);
0524 #if 0
0525     template< class InputIt >
0526     iterator insert( const_iterator pos, InputIt first, InputIt last );
0527     iterator insert( const_iterator pos, std::initializer_list<T> ilist );
0528 #endif
0529     void replace(qsizetype i, parameter_type t)
0530     {
0531         Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
0532         DataPointer oldData;
0533         d.detach(&oldData);
0534         d.data()[i] = t;
0535     }
0536     void replace(qsizetype i, rvalue_ref t)
0537     {
0538         if constexpr (DataPointer::pass_parameter_by_value) {
0539             Q_UNUSED(i);
0540             Q_UNUSED(t);
0541         } else {
0542             Q_ASSERT_X(i >= 0 && i < d->size, "QList<T>::replace", "index out of range");
0543             DataPointer oldData;
0544             d.detach(&oldData);
0545             d.data()[i] = std::move(t);
0546         }
0547     }
0548 
0549     void remove(qsizetype i, qsizetype n = 1);
0550     void removeFirst() noexcept;
0551     void removeLast() noexcept;
0552     value_type takeFirst() { Q_ASSERT(!isEmpty()); value_type v = std::move(first()); d->eraseFirst(); return v; }
0553     value_type takeLast() { Q_ASSERT(!isEmpty()); value_type v = std::move(last()); d->eraseLast(); return v; }
0554 
0555     QList<T> &fill(parameter_type t, qsizetype size = -1);
0556 
0557 #ifndef Q_QDOC
0558     using QListSpecialMethods<T>::contains;
0559     using QListSpecialMethods<T>::indexOf;
0560     using QListSpecialMethods<T>::lastIndexOf;
0561 #else
0562     template <typename AT>
0563     qsizetype indexOf(const AT &t, qsizetype from = 0) const noexcept;
0564     template <typename AT>
0565     qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const noexcept;
0566     template <typename AT>
0567     bool contains(const AT &t) const noexcept;
0568 #endif
0569 
0570     template <typename AT = T>
0571     qsizetype count(const AT &t) const noexcept
0572     {
0573         return qsizetype(std::count(data(), data() + size(), t));
0574     }
0575 
0576     void removeAt(qsizetype i) { remove(i); }
0577     template <typename AT = T>
0578     qsizetype removeAll(const AT &t)
0579     {
0580         return QtPrivate::sequential_erase_with_copy(*this, t);
0581     }
0582 
0583     template <typename AT = T>
0584     bool removeOne(const AT &t)
0585     {
0586         return QtPrivate::sequential_erase_one(*this, t);
0587     }
0588 
0589     template <typename Predicate>
0590     qsizetype removeIf(Predicate pred)
0591     {
0592         return QtPrivate::sequential_erase_if(*this, pred);
0593     }
0594 
0595     T takeAt(qsizetype i) { T t = std::move((*this)[i]); remove(i); return t; }
0596     void move(qsizetype from, qsizetype to)
0597     {
0598         Q_ASSERT_X(from >= 0 && from < size(), "QList::move(qsizetype, qsizetype)", "'from' is out-of-range");
0599         Q_ASSERT_X(to >= 0 && to < size(), "QList::move(qsizetype, qsizetype)", "'to' is out-of-range");
0600         if (from == to) // don't detach when no-op
0601             return;
0602         detach();
0603         T * const b = d->begin();
0604         if (from < to)
0605             std::rotate(b + from, b + from + 1, b + to + 1);
0606         else
0607             std::rotate(b + to, b + from, b + from + 1);
0608     }
0609 
0610     // STL-style
0611     iterator begin() { detach(); return iterator(d->begin()); }
0612     iterator end() { detach(); return iterator(d->end()); }
0613 
0614     const_iterator begin() const noexcept { return const_iterator(d->constBegin()); }
0615     const_iterator end() const noexcept { return const_iterator(d->constEnd()); }
0616     const_iterator cbegin() const noexcept { return const_iterator(d->constBegin()); }
0617     const_iterator cend() const noexcept { return const_iterator(d->constEnd()); }
0618     const_iterator constBegin() const noexcept { return const_iterator(d->constBegin()); }
0619     const_iterator constEnd() const noexcept { return const_iterator(d->constEnd()); }
0620     reverse_iterator rbegin() { return reverse_iterator(end()); }
0621     reverse_iterator rend() { return reverse_iterator(begin()); }
0622     const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
0623     const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
0624     const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
0625     const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
0626 
0627     iterator erase(const_iterator begin, const_iterator end);
0628     inline iterator erase(const_iterator pos) { return erase(pos, pos+1); }
0629 
0630     // more Qt
0631     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
0632     inline const T &first() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
0633     inline const T &constFirst() const noexcept { Q_ASSERT(!isEmpty()); return *begin(); }
0634     inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
0635     inline const T &last() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
0636     inline const T &constLast() const noexcept { Q_ASSERT(!isEmpty()); return *(end()-1); }
0637     inline bool startsWith(parameter_type t) const { return !isEmpty() && first() == t; }
0638     inline bool endsWith(parameter_type t) const { return !isEmpty() && last() == t; }
0639     QList<T> mid(qsizetype pos, qsizetype len = -1) const;
0640 
0641     QList<T> first(qsizetype n) const
0642     { verify(0, n); return QList<T>(begin(), begin() + n); }
0643     QList<T> last(qsizetype n) const
0644     { verify(0, n); return QList<T>(end() - n, end()); }
0645     QList<T> sliced(qsizetype pos) const
0646     { verify(pos, 0); return QList<T>(begin() + pos, end()); }
0647     QList<T> sliced(qsizetype pos, qsizetype n) const
0648     { verify(pos, n); return QList<T>(begin() + pos, begin() + pos + n); }
0649 
0650     T value(qsizetype i) const { return value(i, T()); }
0651     T value(qsizetype i, parameter_type defaultValue) const;
0652 
0653     void swapItemsAt(qsizetype i, qsizetype j) {
0654         Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(),
0655                     "QList<T>::swap", "index out of range");
0656         detach();
0657         qSwap(d->begin()[i], d->begin()[j]);
0658     }
0659 
0660     // STL compatibility
0661     inline void push_back(parameter_type t) { append(t); }
0662     void push_back(rvalue_ref t) { append(std::move(t)); }
0663     void push_front(rvalue_ref t) { prepend(std::move(t)); }
0664     inline void push_front(parameter_type t) { prepend(t); }
0665     void pop_back() noexcept { removeLast(); }
0666     void pop_front() noexcept { removeFirst(); }
0667 
0668     template <typename ...Args>
0669     reference emplace_back(Args&&... args) { return emplaceBack(std::forward<Args>(args)...); }
0670 
0671     inline bool empty() const noexcept
0672     { return d->size == 0; }
0673     inline reference front() { return first(); }
0674     inline const_reference front() const noexcept { return first(); }
0675     inline reference back() { return last(); }
0676     inline const_reference back() const noexcept { return last(); }
0677     void shrink_to_fit() { squeeze(); }
0678 
0679     // comfort
0680     QList<T> &operator+=(const QList<T> &l) { append(l); return *this; }
0681     QList<T> &operator+=(QList<T> &&l) { append(std::move(l)); return *this; }
0682     inline QList<T> operator+(const QList<T> &l) const &
0683     { QList n = *this; n += l; return n; }
0684     QList<T> operator+(const QList<T> &l) &&
0685     { return std::move(*this += l); }
0686     inline QList<T> operator+(QList<T> &&l) const &
0687     { QList n = *this; n += std::move(l); return n; }
0688     QList<T> operator+(QList<T> &&l) &&
0689     { return std::move(*this += std::move(l)); }
0690     inline QList<T> &operator+=(parameter_type t)
0691     { append(t); return *this; }
0692     inline QList<T> &operator<< (parameter_type t)
0693     { append(t); return *this; }
0694     inline QList<T> &operator<<(const QList<T> &l)
0695     { *this += l; return *this; }
0696     inline QList<T> &operator<<(QList<T> &&l)
0697     { *this += std::move(l); return *this; }
0698     inline QList<T> &operator+=(rvalue_ref t)
0699     { append(std::move(t)); return *this; }
0700     inline QList<T> &operator<<(rvalue_ref t)
0701     { append(std::move(t)); return *this; }
0702 
0703     // Consider deprecating in 6.4 or later
0704     static QList<T> fromList(const QList<T> &list) noexcept { return list; }
0705     QList<T> toList() const noexcept { return *this; }
0706 
0707     static inline QList<T> fromVector(const QList<T> &vector) noexcept { return vector; }
0708     inline QList<T> toVector() const noexcept { return *this; }
0709 
0710     template<qsizetype N>
0711     static QList<T> fromReadOnlyData(const T (&t)[N]) noexcept
0712     {
0713         return QList<T>({ nullptr, const_cast<T *>(t), N });
0714     }
0715 };
0716 
0717 template <typename InputIterator,
0718           typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
0719           QtPrivate::IfIsInputIterator<InputIterator> = true>
0720 QList(InputIterator, InputIterator) -> QList<ValueType>;
0721 
0722 template <typename T>
0723 inline void QList<T>::resize_internal(qsizetype newSize)
0724 {
0725     Q_ASSERT(newSize >= 0);
0726 
0727     if (d->needsDetach() || newSize > capacity() - d.freeSpaceAtBegin()) {
0728         d.detachAndGrow(QArrayData::GrowsAtEnd, newSize - d.size, nullptr, nullptr);
0729     } else if (newSize < size()) {
0730         d->truncate(newSize);
0731     }
0732 }
0733 
0734 template <typename T>
0735 void QList<T>::reserve(qsizetype asize)
0736 {
0737     // capacity() == 0 for immutable data, so this will force a detaching below
0738     if (asize <= capacity() - d.freeSpaceAtBegin()) {
0739         if (d->flags() & Data::CapacityReserved)
0740             return;  // already reserved, don't shrink
0741         if (!d->isShared()) {
0742             // accept current allocation, don't shrink
0743             d->setFlag(Data::CapacityReserved);
0744             return;
0745         }
0746     }
0747 
0748     DataPointer detached(qMax(asize, size()));
0749     detached->copyAppend(d->begin(), d->end());
0750     if (detached.d_ptr())
0751         detached->setFlag(Data::CapacityReserved);
0752     d.swap(detached);
0753 }
0754 
0755 template <typename T>
0756 inline void QList<T>::squeeze()
0757 {
0758     if (!d.isMutable())
0759         return;
0760     if (d->needsDetach() || size() < capacity()) {
0761         // must allocate memory
0762         DataPointer detached(size());
0763         if (size()) {
0764             if (d.needsDetach())
0765                 detached->copyAppend(d.data(), d.data() + d.size);
0766             else
0767                 detached->moveAppend(d.data(), d.data() + d.size);
0768         }
0769         d.swap(detached);
0770     }
0771     // We're detached so this is fine
0772     d->clearFlag(Data::CapacityReserved);
0773 }
0774 
0775 template <typename T>
0776 inline void QList<T>::remove(qsizetype i, qsizetype n)
0777 {
0778     Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size), "QList::remove", "index out of range");
0779     Q_ASSERT_X(n >= 0, "QList::remove", "invalid count");
0780 
0781     if (n == 0)
0782         return;
0783 
0784     d.detach();
0785     d->erase(d->begin() + i, n);
0786 }
0787 
0788 template <typename T>
0789 inline void QList<T>::removeFirst() noexcept
0790 {
0791     Q_ASSERT(!isEmpty());
0792     d.detach();
0793     d->eraseFirst();
0794 }
0795 
0796 template <typename T>
0797 inline void QList<T>::removeLast() noexcept
0798 {
0799     Q_ASSERT(!isEmpty());
0800     d.detach();
0801     d->eraseLast();
0802 }
0803 
0804 
0805 template<typename T>
0806 inline T QList<T>::value(qsizetype i, parameter_type defaultValue) const
0807 {
0808     return size_t(i) < size_t(d->size) ? at(i) : defaultValue;
0809 }
0810 
0811 template <typename T>
0812 inline void QList<T>::append(const_iterator i1, const_iterator i2)
0813 {
0814     d->growAppend(i1.i, i2.i);
0815 }
0816 
0817 template <typename T>
0818 inline void QList<T>::append(QList<T> &&other)
0819 {
0820     Q_ASSERT(&other != this);
0821     if (other.isEmpty())
0822         return;
0823     if (other.d->needsDetach() || !std::is_nothrow_move_constructible_v<T>)
0824         return append(other);
0825 
0826     // due to precondition &other != this, we can unconditionally modify 'this'
0827     d.detachAndGrow(QArrayData::GrowsAtEnd, other.size(), nullptr, nullptr);
0828     Q_ASSERT(d.freeSpaceAtEnd() >= other.size());
0829     d->moveAppend(other.d->begin(), other.d->end());
0830 }
0831 
0832 template<typename T>
0833 template<typename... Args>
0834 inline typename QList<T>::reference QList<T>::emplaceFront(Args &&... args)
0835 {
0836     d->emplace(0, std::forward<Args>(args)...);
0837     return *d.begin();
0838 }
0839 
0840 
0841 template <typename T>
0842 inline typename QList<T>::iterator
0843 QList<T>::insert(qsizetype i, qsizetype n, parameter_type t)
0844 {
0845     Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList<T>::insert", "index out of range");
0846     Q_ASSERT_X(n >= 0, "QList::insert", "invalid count");
0847     if (Q_LIKELY(n))
0848         d->insert(i, n, t);
0849     return begin() + i;
0850 }
0851 
0852 template <typename T>
0853 template <typename ...Args>
0854 typename QList<T>::iterator
0855 QList<T>::emplace(qsizetype i, Args&&... args)
0856 {
0857     Q_ASSERT_X(i >= 0 && i <= d->size, "QList<T>::insert", "index out of range");
0858     d->emplace(i, std::forward<Args>(args)...);
0859     return begin() + i;
0860 }
0861 
0862 template<typename T>
0863 template<typename... Args>
0864 inline typename QList<T>::reference QList<T>::emplaceBack(Args &&... args)
0865 {
0866     d->emplace(d->size, std::forward<Args>(args)...);
0867     return *(end() - 1);
0868 }
0869 
0870 template <typename T>
0871 typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterator aend)
0872 {
0873     Q_ASSERT_X(isValidIterator(abegin), "QList::erase", "The specified iterator argument 'abegin' is invalid");
0874     Q_ASSERT_X(isValidIterator(aend), "QList::erase", "The specified iterator argument 'aend' is invalid");
0875     Q_ASSERT(aend >= abegin);
0876 
0877     qsizetype i = std::distance(constBegin(), abegin);
0878     qsizetype n = std::distance(abegin, aend);
0879     remove(i, n);
0880 
0881     return begin() + i;
0882 }
0883 
0884 template <typename T>
0885 inline QList<T> &QList<T>::fill(parameter_type t, qsizetype newSize)
0886 {
0887     if (newSize == -1)
0888         newSize = size();
0889     if (d->needsDetach() || newSize > capacity()) {
0890         // must allocate memory
0891         DataPointer detached(d->detachCapacity(newSize));
0892         detached->copyAppend(newSize, t);
0893         d.swap(detached);
0894     } else {
0895         // we're detached
0896         const T copy(t);
0897         d->assign(d.begin(), d.begin() + qMin(size(), newSize), t);
0898         if (newSize > size()) {
0899             d->copyAppend(newSize - size(), copy);
0900         } else if (newSize < size()) {
0901             d->truncate(newSize);
0902         }
0903     }
0904     return *this;
0905 }
0906 
0907 namespace QtPrivate {
0908 template <typename T, typename U>
0909 qsizetype indexOf(const QList<T> &vector, const U &u, qsizetype from) noexcept
0910 {
0911     if (from < 0)
0912         from = qMax(from + vector.size(), qsizetype(0));
0913     if (from < vector.size()) {
0914         auto n = vector.begin() + from - 1;
0915         auto e = vector.end();
0916         while (++n != e)
0917             if (*n == u)
0918                 return qsizetype(n - vector.begin());
0919     }
0920     return -1;
0921 }
0922 
0923 template <typename T, typename U>
0924 qsizetype lastIndexOf(const QList<T> &vector, const U &u, qsizetype from) noexcept
0925 {
0926     if (from < 0)
0927         from += vector.d->size;
0928     else if (from >= vector.size())
0929         from = vector.size() - 1;
0930     if (from >= 0) {
0931         auto b = vector.begin();
0932         auto n = vector.begin() + from + 1;
0933         while (n != b) {
0934             if (*--n == u)
0935                 return qsizetype(n - b);
0936         }
0937     }
0938     return -1;
0939 }
0940 }
0941 
0942 template <typename T>
0943 template <typename AT>
0944 qsizetype QListSpecialMethodsBase<T>::indexOf(const AT &t, qsizetype from) const noexcept
0945 {
0946     return QtPrivate::indexOf(*self(), t, from);
0947 }
0948 
0949 template <typename T>
0950 template <typename AT>
0951 qsizetype QListSpecialMethodsBase<T>::lastIndexOf(const AT &t, qsizetype from) const noexcept
0952 {
0953     return QtPrivate::lastIndexOf(*self(), t, from);
0954 }
0955 
0956 template <typename T>
0957 inline QList<T> QList<T>::mid(qsizetype pos, qsizetype len) const
0958 {
0959     qsizetype p = pos;
0960     qsizetype l = len;
0961     using namespace QtPrivate;
0962     switch (QContainerImplHelper::mid(d.size, &p, &l)) {
0963     case QContainerImplHelper::Null:
0964     case QContainerImplHelper::Empty:
0965         return QList();
0966     case QContainerImplHelper::Full:
0967         return *this;
0968     case QContainerImplHelper::Subset:
0969         break;
0970     }
0971 
0972     // Allocate memory
0973     DataPointer copied(l);
0974     copied->copyAppend(data() + p, data() + p + l);
0975     return copied;
0976 }
0977 
0978 Q_DECLARE_SEQUENTIAL_ITERATOR(List)
0979 Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List)
0980 
0981 template <typename T>
0982 size_t qHash(const QList<T> &key, size_t seed = 0)
0983     noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed)))
0984 {
0985     return qHashRange(key.cbegin(), key.cend(), seed);
0986 }
0987 
0988 template <typename T, typename AT>
0989 qsizetype erase(QList<T> &list, const AT &t)
0990 {
0991     return QtPrivate::sequential_erase(list, t);
0992 }
0993 
0994 template <typename T, typename Predicate>
0995 qsizetype erase_if(QList<T> &list, Predicate pred)
0996 {
0997     return QtPrivate::sequential_erase_if(list, pred);
0998 }
0999 
1000 // ### Qt 7 char32_t
1001 QList<uint> QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); }
1002 
1003 QT_END_NAMESPACE
1004 
1005 #include <QtCore/qbytearraylist.h>
1006 #include <QtCore/qstringlist.h>
1007 
1008 #endif // QLIST_H