Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:21

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