From 03326a2fec416405b437089874f6439e937bbada Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 27 May 2020 09:58:12 +0200 Subject: Move implementation of QVector/List back to qlist.h And name the main class QList. That's also the one we document. This gives less porting pain for our users, and a lot less churn in our API, as we use QList in Qt 5 in 95% of our API. In addition, it gives more consistent naming with QStringList and QByteArrayList and disambiguates QList vs QVector(2|3|4)D. Fixes: QTBUG-84468 Change-Id: I3cba9d1d3179969d8bf9320b31be2230d021d1a9 Reviewed-by: Volker Hilsheimer --- .../doc/snippets/code/src_corelib_tools_qlist.cpp | 210 ++ .../snippets/code/src_corelib_tools_qvector.cpp | 229 -- src/corelib/global/qtypeinfo.h | 2 +- src/corelib/itemmodels/qitemselectionmodel.h | 2 +- src/corelib/kernel/qmetaobject.cpp | 2 +- src/corelib/kernel/qmetatype.h | 10 +- src/corelib/text/qbytearraylist.h | 16 +- src/corelib/text/qstring.h | 1 - src/corelib/text/qstringalgorithms.h | 3 +- src/corelib/text/qstringlist.h | 70 +- src/corelib/text/qstringtokenizer.h | 2 +- src/corelib/tools/qcontainerfwd.h | 4 +- src/corelib/tools/qlist.cpp | 8 +- src/corelib/tools/qlist.h | 756 +++++- src/corelib/tools/qlist.qdoc | 1472 ++++++++++ src/corelib/tools/qvector.h | 755 +----- src/corelib/tools/qvector.qdoc | 1473 ---------- src/gui/image/qimage.h | 2 +- src/gui/painting/qregion.h | 2 +- src/gui/text/qtextdocument.h | 2 +- src/gui/text/qtextengine_p.h | 6 +- src/network/access/qhsts_p.h | 3 +- src/network/ssl/qdtls.h | 2 +- src/plugins/generic/tuiotouch/qoscbundle_p.h | 14 +- src/plugins/generic/tuiotouch/qoscmessage_p.h | 5 +- src/sql/kernel/qsqlcachedresult_p.h | 2 +- src/sql/kernel/qsqlresult.h | 3 +- src/widgets/kernel/qlayoutengine_p.h | 3 +- sync.profile | 2 +- .../corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 33 +- .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 6 +- .../serialization/qxmlstream/tst_qxmlstream.cpp | 2 +- tests/auto/corelib/tools/CMakeLists.txt | 2 +- .../tst_containerapisymmetry.cpp | 2 +- tests/auto/corelib/tools/qlist/.gitignore | 1 + tests/auto/corelib/tools/qlist/CMakeLists.txt | 13 + tests/auto/corelib/tools/qlist/qlist.pro | 7 + tests/auto/corelib/tools/qlist/tst_qlist.cpp | 2834 ++++++++++++++++++++ tests/auto/corelib/tools/qvector/.gitignore | 1 - tests/auto/corelib/tools/qvector/CMakeLists.txt | 13 - tests/auto/corelib/tools/qvector/qvector.pro | 7 - tests/auto/corelib/tools/qvector/tst_qvector.cpp | 2834 -------------------- tests/auto/corelib/tools/tools.pro | 2 +- .../auto/dbus/qdbusmetatype/tst_qdbusmetatype.cpp | 2 +- tests/auto/tools/moc/allmocs_baseline_in.json | 12 +- tests/auto/tools/moc/tst_moc.cpp | 22 +- 46 files changed, 5407 insertions(+), 5447 deletions(-) create mode 100644 src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp delete mode 100644 src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp create mode 100644 src/corelib/tools/qlist.qdoc delete mode 100644 src/corelib/tools/qvector.qdoc create mode 100644 tests/auto/corelib/tools/qlist/.gitignore create mode 100644 tests/auto/corelib/tools/qlist/CMakeLists.txt create mode 100644 tests/auto/corelib/tools/qlist/qlist.pro create mode 100644 tests/auto/corelib/tools/qlist/tst_qlist.cpp delete mode 100644 tests/auto/corelib/tools/qvector/.gitignore delete mode 100644 tests/auto/corelib/tools/qvector/CMakeLists.txt delete mode 100644 tests/auto/corelib/tools/qvector/qvector.pro delete mode 100644 tests/auto/corelib/tools/qvector/tst_qvector.cpp diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp new file mode 100644 index 0000000000..cdf1ae0eb1 --- /dev/null +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlist.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +QList integerVector; +QList stringVector; +//! [0] + + +//! [1] +QList vector(200); +//! [1] + + +//! [2] +QList vector(200, "Pass"); +//! [2] + + +//! [3] +if (vector[0] == "Liz") + vector[0] = "Elizabeth"; +//! [3] + + +//! [4] +for (int i = 0; i < vector.size(); ++i) { + if (vector.at(i) == "Alfonso") + cout << "Found Alfonso at position " << i << Qt::endl; +} +//! [4] + + +//! [5] +int i = vector.indexOf("Harumi"); +if (i != -1) + cout << "First occurrence of Harumi is at position " << i << Qt::endl; +//! [5] + + +//! [6] +QList vector(10); +int *data = vector.data(); +for (int i = 0; i < 10; ++i) + data[i] = 2 * i; +//! [6] + + +//! [7] +QList vector; +vector.append("one"); +vector.append("two"); +QString three = "three"; +vector.append(three); +// vector: ["one", "two", "three"] +// three: "three" +//! [7] + + +//! [move-append] +QList vector; +vector.append("one"); +vector.append("two"); +QString three = "three"; +vector.append(std::move(three)); +// vector: ["one", "two", "three"] +// three: "" +//! [move-append] + + +//! [emplace] +QList vector{"a", "ccc"}; +vector.emplace(1, 2, 'b'); +// vector: ["a", "bb", "ccc"] +//! [emplace] + + +//! [emplace-back] +QList vector{"one", "two"}; +vector.emplaceBack(3, 'a'); +qDebug() << vector; +// vector: ["one", "two", "aaa"] +//! [emplace-back] + + +//! [emplace-back-ref] +QList vector; +auto &ref = vector.emplaceBack(); +ref = "one"; +// vector: ["one"] +//! [emplace-back-ref] + + +//! [8] +QList vector; +vector.prepend("one"); +vector.prepend("two"); +vector.prepend("three"); +// vector: ["three", "two", "one"] +//! [8] + + +//! [9] +QList vector; +vector << "alpha" << "beta" << "delta"; +vector.insert(2, "gamma"); +// vector: ["alpha", "beta", "gamma", "delta"] +//! [9] + + +//! [10] +QList vector; +vector << 2.718 << 1.442 << 0.4342; +vector.insert(1, 3, 9.9); +// vector: [2.718, 9.9, 9.9, 9.9, 1.442, 0.4342] +//! [10] + + +//! [11] +QList vector(3); +vector.fill("Yes"); +// vector: ["Yes", "Yes", "Yes"] + +vector.fill("oh", 5); +// vector: ["oh", "oh", "oh", "oh", "oh"] +//! [11] + + +//! [12] +QList vector; +vector << "A" << "B" << "C" << "B" << "A"; +vector.indexOf("B"); // returns 1 +vector.indexOf("B", 1); // returns 1 +vector.indexOf("B", 2); // returns 3 +vector.indexOf("X"); // returns -1 +//! [12] + + +//! [13] +QList vector; +vector << "A" << "B" << "C" << "B" << "A"; +vector.lastIndexOf("B"); // returns 3 +vector.lastIndexOf("B", 3); // returns 3 +vector.lastIndexOf("B", 2); // returns 1 +vector.lastIndexOf("X"); // returns -1 +//! [13] + +//! [16] +std::vector stdvector; +vector.push_back(1.2); +vector.push_back(0.5); +vector.push_back(3.14); + +QList vector = QList::fromStdVector(stdvector); +//! [16] + + +//! [17] +QList vector; +vector << 1.2 << 0.5 << 3.14; + +std::vector stdvector = vector.toStdVector(); +//! [17] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp deleted file mode 100644 index 76a8d68f64..0000000000 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//! [0] -QVector integerVector; -QVector stringVector; -//! [0] - - -//! [1] -QVector vector(200); -//! [1] - - -//! [2] -QVector vector(200, "Pass"); -//! [2] - - -//! [3] -if (vector[0] == "Liz") - vector[0] = "Elizabeth"; -//! [3] - - -//! [4] -for (int i = 0; i < vector.size(); ++i) { - if (vector.at(i) == "Alfonso") - cout << "Found Alfonso at position " << i << Qt::endl; -} -//! [4] - - -//! [5] -int i = vector.indexOf("Harumi"); -if (i != -1) - cout << "First occurrence of Harumi is at position " << i << Qt::endl; -//! [5] - - -//! [6] -QVector vector(10); -int *data = vector.data(); -for (int i = 0; i < 10; ++i) - data[i] = 2 * i; -//! [6] - - -//! [7] -QVector vector; -vector.append("one"); -vector.append("two"); -QString three = "three"; -vector.append(three); -// vector: ["one", "two", "three"] -// three: "three" -//! [7] - - -//! [move-append] -QVector vector; -vector.append("one"); -vector.append("two"); -QString three = "three"; -vector.append(std::move(three)); -// vector: ["one", "two", "three"] -// three: "" -//! [move-append] - - -//! [emplace] -QVector vector{"a", "ccc"}; -vector.emplace(1, 2, 'b'); -// vector: ["a", "bb", "ccc"] -//! [emplace] - - -//! [emplace-back] -QVector vector{"one", "two"}; -vector.emplaceBack(3, 'a'); -qDebug() << vector; -// vector: ["one", "two", "aaa"] -//! [emplace-back] - - -//! [emplace-back-ref] -QVector vector; -auto &ref = vector.emplaceBack(); -ref = "one"; -// vector: ["one"] -//! [emplace-back-ref] - - -//! [8] -QVector vector; -vector.prepend("one"); -vector.prepend("two"); -vector.prepend("three"); -// vector: ["three", "two", "one"] -//! [8] - - -//! [9] -QVector vector; -vector << "alpha" << "beta" << "delta"; -vector.insert(2, "gamma"); -// vector: ["alpha", "beta", "gamma", "delta"] -//! [9] - - -//! [10] -QVector vector; -vector << 2.718 << 1.442 << 0.4342; -vector.insert(1, 3, 9.9); -// vector: [2.718, 9.9, 9.9, 9.9, 1.442, 0.4342] -//! [10] - - -//! [11] -QVector vector(3); -vector.fill("Yes"); -// vector: ["Yes", "Yes", "Yes"] - -vector.fill("oh", 5); -// vector: ["oh", "oh", "oh", "oh", "oh"] -//! [11] - - -//! [12] -QVector vector; -vector << "A" << "B" << "C" << "B" << "A"; -vector.indexOf("B"); // returns 1 -vector.indexOf("B", 1); // returns 1 -vector.indexOf("B", 2); // returns 3 -vector.indexOf("X"); // returns -1 -//! [12] - - -//! [13] -QList vector; -vector << "A" << "B" << "C" << "B" << "A"; -vector.lastIndexOf("B"); // returns 3 -vector.lastIndexOf("B", 3); // returns 3 -vector.lastIndexOf("B", 2); // returns 1 -vector.lastIndexOf("X"); // returns -1 -//! [13] - - -//! [14] -QVector vect; -vect << "red" << "green" << "blue" << "black"; - -QList list = vect.toList(); -// list: ["red", "green", "blue", "black"] -//! [14] - - -//! [15] -QStringList list; -list << "Sven" << "Kim" << "Ola"; - -QVector vect = QVector::fromList(list); -// vect: ["Sven", "Kim", "Ola"] -//! [15] - - -//! [16] -std::vector stdvector; -vector.push_back(1.2); -vector.push_back(0.5); -vector.push_back(3.14); - -QVector vector = QVector::fromStdVector(stdvector); -//! [16] - - -//! [17] -QVector vector; -vector << 1.2 << 0.5 << 3.14; - -std::vector stdvector = vector.toStdVector(); -//! [17] diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 175d5205af..121c9fdcd8 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -182,7 +182,7 @@ public: \ }; \ } -Q_DECLARE_MOVABLE_CONTAINER(QVector); +Q_DECLARE_MOVABLE_CONTAINER(QList); Q_DECLARE_MOVABLE_CONTAINER(QQueue); Q_DECLARE_MOVABLE_CONTAINER(QStack); Q_DECLARE_MOVABLE_CONTAINER(QSet); diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index 529dc6f100..c1ce49521c 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -223,7 +223,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) # define Q_TEMPLATE_EXTERN extern # endif # endif -Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector; +Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QList; #endif // Q_CC_MSVC class Q_CORE_EXPORT QItemSelection : public QList diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 6799057080..c20fb5b6e0 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -682,7 +682,7 @@ static void argumentTypesFromString(const char *str, const char *end, ++str; } QByteArray argType(begin, str - begin); - argType.replace("QList<", "QVector<"); + argType.replace("QVector<", "QList<"); types += QArgumentType(std::move(argType)); } } diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 196df677e9..c7e754cb5c 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -232,7 +232,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); TypeName = Id, #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \ - F(QVector) \ + F(QList) \ F(QQueue) \ F(QStack) \ F(QSet) \ @@ -2014,7 +2014,7 @@ typedef QHash QVariantHash; #ifdef Q_CLANG_QDOC class QByteArrayList; #else -typedef QVector QByteArrayList; +using QByteArrayList = QList; #endif #define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \ @@ -2515,9 +2515,9 @@ public: } #endif - if (skipToken(begin, end, "QList")) { - // Replace QList by QVector - appendStr("QVector"); + if (skipToken(begin, end, "QVector")) { + // Replace QVector by QList + appendStr("QList"); } if (skipToken(begin, end, "QPair")) { diff --git a/src/corelib/text/qbytearraylist.h b/src/corelib/text/qbytearraylist.h index d02fa6d20f..3f85a24329 100644 --- a/src/corelib/text/qbytearraylist.h +++ b/src/corelib/text/qbytearraylist.h @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include +#include #ifndef QBYTEARRAYLIST_H #define QBYTEARRAYLIST_H @@ -49,12 +49,12 @@ QT_BEGIN_NAMESPACE #if !defined(QT_NO_JAVA_STYLE_ITERATORS) -typedef QVectorIterator QByteArrayListIterator; -typedef QMutableVectorIterator QMutableByteArrayListIterator; +typedef QListIterator QByteArrayListIterator; +typedef QMutableListIterator QMutableByteArrayListIterator; #endif #ifndef Q_CLANG_QDOC -typedef QVector QByteArrayList; +typedef QList QByteArrayList; namespace QtPrivate { QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength); @@ -63,14 +63,14 @@ namespace QtPrivate { #endif #ifdef Q_CLANG_QDOC -class QByteArrayList : public QVector +class QByteArrayList : public QList #else -template <> struct QVectorSpecialMethods +template <> struct QListSpecialMethods #endif { #ifndef Q_CLANG_QDOC protected: - ~QVectorSpecialMethods() = default; + ~QListSpecialMethods() = default; #endif public: inline QByteArray join() const @@ -81,7 +81,7 @@ public: { return QtPrivate::QByteArrayList_join(self(), &sep, 1); } private: - typedef QVector Self; + typedef QList Self; Self *self() { return static_cast(this); } const Self *self() const { return static_cast(this); } }; diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index 77a95c6280..f14644d956 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -77,7 +77,6 @@ class QRegularExpressionMatch; class QString; class QStringList; class QStringRef; -template class QVector; namespace QtPrivate { template class BoolList; diff --git a/src/corelib/text/qstringalgorithms.h b/src/corelib/text/qstringalgorithms.h index f1aa052eac..3b67739232 100644 --- a/src/corelib/text/qstringalgorithms.h +++ b/src/corelib/text/qstringalgorithms.h @@ -41,7 +41,7 @@ #define QSTRINGALGORITHMS_H #include - +#include #if 0 #pragma qt_class(QStringAlgorithms) #endif @@ -52,7 +52,6 @@ class QByteArray; class QLatin1String; class QStringView; class QChar; -template class QVector; namespace QtPrivate { diff --git a/src/corelib/text/qstringlist.h b/src/corelib/text/qstringlist.h index b94671746b..9c4daedd4b 100644 --- a/src/corelib/text/qstringlist.h +++ b/src/corelib/text/qstringlist.h @@ -38,7 +38,7 @@ ** ****************************************************************************/ -#include +#include #ifndef QSTRINGLIST_H #define QSTRINGLIST_H @@ -53,21 +53,21 @@ QT_BEGIN_NAMESPACE class QRegularExpression; #if !defined(QT_NO_JAVA_STYLE_ITERATORS) -typedef QVectorIterator QStringListIterator; -typedef QMutableVectorIterator QMutableStringListIterator; +using QStringListIterator = QListIterator; +using QMutableStringListIterator = QMutableListIterator; #endif class QStringList; #ifdef Q_QDOC -class QStringList : public QVector +class QStringList : public QList #else -template <> struct QVectorSpecialMethods +template <> struct QListSpecialMethods #endif { #ifndef Q_QDOC protected: - ~QVectorSpecialMethods() = default; + ~QListSpecialMethods() = default; #endif public: inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive); @@ -101,23 +101,23 @@ private: }; // ### Qt6: check if there's a better way -class QStringList : public QVector +class QStringList : public QList { #endif public: inline QStringList() noexcept { } inline explicit QStringList(const QString &i) { append(i); } - inline QStringList(const QVector &l) : QVector(l) { } - inline QStringList(QVector &&l) noexcept : QVector(std::move(l)) { } - inline QStringList(std::initializer_list args) : QVector(args) { } + inline QStringList(const QList &l) : QList(l) { } + inline QStringList(QList &&l) noexcept : QList(std::move(l)) { } + inline QStringList(std::initializer_list args) : QList(args) { } template = true> inline QStringList(InputIterator first, InputIterator last) - : QVector(first, last) { } + : QList(first, last) { } - QStringList &operator=(const QVector &other) - { QVector::operator=(other); return *this; } - QStringList &operator=(QVector &&other) noexcept - { QVector::operator=(std::move(other)); return *this; } + QStringList &operator=(const QList &other) + { QList::operator=(other); return *this; } + QStringList &operator=(QList &&other) noexcept + { QList::operator=(std::move(other)); return *this; } #if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -131,7 +131,7 @@ public: { append(str); return *this; } inline QStringList &operator<<(const QStringList &l) { *this += l; return *this; } - inline QStringList &operator<<(const QVector &l) + inline QStringList &operator<<(const QList &l) { *this += l; return *this; } inline int indexOf(QStringView str, int from = 0) const; @@ -145,16 +145,16 @@ public: inline int lastIndexOf(const QRegularExpression &re, int from = -1) const; #endif // QT_CONFIG(regularexpression) - using QVector::indexOf; - using QVector::lastIndexOf; + using QList::indexOf; + using QList::lastIndexOf; }; Q_DECLARE_TYPEINFO(QStringList, Q_MOVABLE_TYPE); #ifndef Q_QDOC -inline QStringList *QVectorSpecialMethods::self() +inline QStringList *QListSpecialMethods::self() { return static_cast(this); } -inline const QStringList *QVectorSpecialMethods::self() const +inline const QStringList *QListSpecialMethods::self() const { return static_cast(this); } namespace QtPrivate { @@ -190,45 +190,45 @@ namespace QtPrivate { #endif // QT_CONFIG(regularexpression) } -inline void QVectorSpecialMethods::sort(Qt::CaseSensitivity cs) +inline void QListSpecialMethods::sort(Qt::CaseSensitivity cs) { QtPrivate::QStringList_sort(self(), cs); } -inline int QVectorSpecialMethods::removeDuplicates() +inline int QListSpecialMethods::removeDuplicates() { return QtPrivate::QStringList_removeDuplicates(self()); } #if QT_STRINGVIEW_LEVEL < 2 -inline QString QVectorSpecialMethods::join(const QString &sep) const +inline QString QListSpecialMethods::join(const QString &sep) const { return QtPrivate::QStringList_join(self(), sep.constData(), sep.length()); } #endif -inline QString QVectorSpecialMethods::join(QStringView sep) const +inline QString QListSpecialMethods::join(QStringView sep) const { return QtPrivate::QStringList_join(self(), sep); } -QString QVectorSpecialMethods::join(QLatin1String sep) const +QString QListSpecialMethods::join(QLatin1String sep) const { return QtPrivate::QStringList_join(*self(), sep); } -inline QString QVectorSpecialMethods::join(QChar sep) const +inline QString QListSpecialMethods::join(QChar sep) const { return QtPrivate::QStringList_join(self(), &sep, 1); } -inline QStringList QVectorSpecialMethods::filter(QStringView str, Qt::CaseSensitivity cs) const +inline QStringList QListSpecialMethods::filter(QStringView str, Qt::CaseSensitivity cs) const { return QtPrivate::QStringList_filter(self(), str, cs); } #if QT_STRINGVIEW_LEVEL < 2 -inline QStringList QVectorSpecialMethods::filter(const QString &str, Qt::CaseSensitivity cs) const +inline QStringList QListSpecialMethods::filter(const QString &str, Qt::CaseSensitivity cs) const { return QtPrivate::QStringList_filter(self(), str, cs); } @@ -251,33 +251,33 @@ inline bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const return QtPrivate::QStringList_contains(this, str, cs); } -inline QStringList &QVectorSpecialMethods::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs) +inline QStringList &QListSpecialMethods::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs) { QtPrivate::QStringList_replaceInStrings(self(), before, after, cs); return *self(); } #if QT_STRINGVIEW_LEVEL < 2 -inline QStringList &QVectorSpecialMethods::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) +inline QStringList &QListSpecialMethods::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) { QtPrivate::QStringList_replaceInStrings(self(), before, after, cs); return *self(); } -inline QStringList &QVectorSpecialMethods::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs) +inline QStringList &QListSpecialMethods::replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs) { QtPrivate::QStringList_replaceInStrings(self(), before, qToStringViewIgnoringNull(after), cs); return *self(); } -inline QStringList &QVectorSpecialMethods::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs) +inline QStringList &QListSpecialMethods::replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs) { QtPrivate::QStringList_replaceInStrings(self(), QStringView(before), after, cs); return *self(); } #endif -inline QStringList operator+(const QVector &one, const QStringList &other) +inline QStringList operator+(const QList &one, const QStringList &other) { QStringList n = one; n += other; @@ -305,13 +305,13 @@ inline int QStringList::lastIndexOf(QLatin1String string, int from) const } #if QT_CONFIG(regularexpression) -inline QStringList &QVectorSpecialMethods::replaceInStrings(const QRegularExpression &rx, const QString &after) +inline QStringList &QListSpecialMethods::replaceInStrings(const QRegularExpression &rx, const QString &after) { QtPrivate::QStringList_replaceInStrings(self(), rx, after); return *self(); } -inline QStringList QVectorSpecialMethods::filter(const QRegularExpression &rx) const +inline QStringList QListSpecialMethods::filter(const QRegularExpression &rx) const { return QtPrivate::QStringList_filter(self(), rx); } diff --git a/src/corelib/text/qstringtokenizer.h b/src/corelib/text/qstringtokenizer.h index 31bbbf01c8..d042fbbdab 100644 --- a/src/corelib/text/qstringtokenizer.h +++ b/src/corelib/text/qstringtokenizer.h @@ -40,11 +40,11 @@ #define QSTRINGTOKENIZER_H #include +#include QT_BEGIN_NAMESPACE template class QStringBuilder; -template class QVector; #if defined(Q_QDOC) || 1 || (defined(__cpp_range_based_for) && __cpp_range_based_for >= 201603) # define Q_STRINGTOKENIZER_USE_SENTINEL diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h index fd4701a8b1..715583e03b 100644 --- a/src/corelib/tools/qcontainerfwd.h +++ b/src/corelib/tools/qcontainerfwd.h @@ -56,8 +56,8 @@ template class QQueue; template class QSet; template class QStack; template class QVarLengthArray; -template class QVector; -template using QList = QVector; +template class QList; +template using QVector = QList; QT_END_NAMESPACE diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 62201fd5d6..cdcfc30f28 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE /* ### 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 QVector and - ### QVector respectively. + ### Qt exports QPolygon and QPolygonF that inherit QList and + ### QList respectively. */ #if defined(Q_CC_MSVC) && defined(QT_BUILD_CORE_LIB) @@ -59,8 +59,8 @@ QT_BEGIN_INCLUDE_NAMESPACE #include QT_END_INCLUDE_NAMESPACE -template class Q_CORE_EXPORT QVector; -template class Q_CORE_EXPORT QVector; +template class Q_CORE_EXPORT QList; +template class Q_CORE_EXPORT QList; #endif QT_END_NAMESPACE 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 -#include +#include +#include +#include +#include + +#include +#include +#include +#include -#if !defined(QT_NO_JAVA_STYLE_ITERATORS) QT_BEGIN_NAMESPACE + +namespace QtPrivate { + template int indexOf(const QList &list, const U &u, int from); + template int lastIndexOf(const QList &list, const U &u, int from); +} + +template struct QListSpecialMethods +{ +protected: + ~QListSpecialMethods() = default; +}; +template <> struct QListSpecialMethods; +template <> struct QListSpecialMethods; + +template +class QList +#ifndef Q_QDOC + : public QListSpecialMethods +#endif +{ + typedef QTypedArrayData Data; + typedef QArrayDataOps DataOps; + typedef QArrayDataPointer DataPointer; + class DisableRValueRefs {}; + + DataPointer d; + + template friend int QtPrivate::indexOf(const QList &list, const U &u, int from); + template friend int QtPrivate::lastIndexOf(const QList &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 reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename DataPointer::parameter_type parameter_type; + using rvalue_ref = typename std::conditional::type; + +private: + void resize_internal(int i, Qt::Initialization); + bool isValidIterator(const_iterator i) const + { + const std::less 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 &other) noexcept : d(other.d) {} + QList(QList &&other) noexcept : d(std::move(other.d)) {} + inline QList(std::initializer_list args) + : d(Data::allocate(args.size())) + { + if (args.size()) + d->copyAppend(args.begin(), args.end()); + } + + ~QList() /*noexcept(std::is_nothrow_destructible::value)*/ {} + QList &operator=(const QList &other) { d = other.d; return *this; } + QList &operator=(QList &&other) noexcept(std::is_nothrow_destructible::value) + { + d = std::move(other.d); + return *this; + } + QList &operator=(std::initializer_list args) + { + d = DataPointer(Data::allocate(args.size())); + if (args.size()) + d->copyAppend(args.begin(), args.end()); + return *this; + } + template = true> + QList(InputIterator i1, InputIterator i2) + : d(Data::allocate(std::distance(i1, i2))) + { + if (std::distance(i1, i2)) + d->copyAppend(i1, i2); + } + + template = true> + QList(InputIterator i1, InputIterator i2) + : QList() + { + QtPrivate::reserveIfForwardIterator(this, i1, i2); + std::copy(i1, i2, std::back_inserter(*this)); + } + + void swap(QList &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 &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 &l) { append(l.constBegin(), l.constEnd()); } + void prepend(rvalue_ref t); + void prepend(const T &t); + + template + reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward(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 + 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)...); + } + + template + 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 ilist ); +#endif + void replace(int i, const T &t) + { + Q_ASSERT_X(i >= 0 && i < d->size, "QList::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::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 &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 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::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 + reference emplace_back(Args&&... args) { return emplaceBack(std::forward(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 &operator+=(const QList &l) { append(l.cbegin(), l.cend()); return *this; } + inline QList operator+(const QList &l) const + { QList n = *this; n += l; return n; } + inline QList &operator+=(const T &t) + { append(t); return *this; } + inline QList &operator<< (const T &t) + { append(t); return *this; } + inline QList &operator<<(const QList &l) + { *this += l; return *this; } + inline QList &operator+=(rvalue_ref t) + { append(std::move(t)); return *this; } + inline QList &operator<<(rvalue_ref t) + { append(std::move(t)); return *this; } + + // Consider deprecating in 6.4 or later + static QList fromList(const QList &list) { return list; } + QList toList() const { return *this; } + + static inline QList fromVector(const QList &vector) { return vector; } + inline QList toVector() const { return *this; } +}; + +#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606 +template ::value_type, + QtPrivate::IfIsInputIterator = true> +QList(InputIterator, InputIterator) -> QList; +#endif + +template +inline void QList::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 +void QList::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 +inline void QList::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 +inline void QList::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 +inline void QList::prepend(const T &t) +{ insert(0, 1, t); } +template +void QList::prepend(rvalue_ref t) +{ insert(0, std::move(t)); } + template -using QMutableListIterator = QMutableVectorIterator; -template -using QListIterator = QVectorIterator; -QT_END_NAMESPACE +inline T QList::value(int i, const T &defaultValue) const +{ + return size_t(i) < size_t(d->size) ? at(i) : defaultValue; +} + +template +inline void QList::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 +inline typename QList::iterator +QList::insert(int i, int n, parameter_type t) +{ + Q_ASSERT_X(size_t(i) <= size_t(d->size), "QList::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 +template +typename QList::iterator +QList::emplace(int i, Args&&... args) +{ + Q_ASSERT_X(i >= 0 && i <= d->size, "QList::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)...); + + // 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)...); + } + return d.begin() + i; +} + +template +typename QList::iterator QList::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 +inline QList &QList::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 +int indexOf(const QList &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 +int lastIndexOf(const QList &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 +int QList::indexOf(const T &t, int from) const noexcept +{ + return QtPrivate::indexOf(*this, t, from); +} + +template +int QList::lastIndexOf(const T &t, int from) const noexcept +{ + return QtPrivate::lastIndexOf(*this, t, from); +} + +template +inline QList QList::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 +size_t qHash(const QList &key, size_t seed = 0) + noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed))) +{ + return qHashRange(key.cbegin(), key.cend(), seed); +} + +template +auto operator<(const QList &lhs, const QList &rhs) + noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()))) + -> decltype(std::declval() < std::declval()) +{ + return std::lexicographical_compare(lhs.begin(), lhs.end(), + rhs.begin(), rhs.end()); +} + +template +auto operator>(const QList &lhs, const QList &rhs) + noexcept(noexcept(lhs < rhs)) + -> decltype(lhs < rhs) +{ + return rhs < lhs; +} + +template +auto operator<=(const QList &lhs, const QList &rhs) + noexcept(noexcept(lhs < rhs)) + -> decltype(lhs < rhs) +{ + return !(lhs > rhs); +} + +template +auto operator>=(const QList &lhs, const QList &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 and + ### QList respectively. +*/ + +#if defined(Q_CC_MSVC) && !defined(QT_BUILD_CORE_LIB) +QT_BEGIN_INCLUDE_NAMESPACE +#include +QT_END_INCLUDE_NAMESPACE +extern template class Q_CORE_EXPORT QList; +extern template class Q_CORE_EXPORT QList; #endif +QList QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); } + +QT_END_NAMESPACE + #include #include diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc new file mode 100644 index 0000000000..c0af194858 --- /dev/null +++ b/src/corelib/tools/qlist.qdoc @@ -0,0 +1,1472 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QVector + \inmodule QtCore + \brief QVector is an alias for QList. + + Please see the QList documentation for details. +*/ + +/*! + \class QList + \inmodule QtCore + \brief The QList class is a template class that provides a dynamic array. + + \ingroup tools + \ingroup shared + + \reentrant + + QList\ is one of Qt's generic \l{container classes}. It + stores its items in adjacent memory locations and provides fast + index-based access. QVector\ used to be a different class in + Qt 5, but is now a simple alias to QList. + + QList\ and QVarLengthArray\ + provide similar APIs and functionality. They are often interchangeable, + but there are performance consequences. Here is an overview of use cases: + + \list + \li QList should be your default first choice. + \li QVarLengthArray provides an array that reserves space on the stack, + but can dynamically grow onto the heap if required. It's good to + use for short lived containers that are usually small. + \li If you need a real linked list, which guarantees + \l{Algorithmic Complexity}{constant time} insertions mid-list and + uses iterators to items rather than indexes, use std::list. + \endlist + + \note QList and QVarLengthArray both guarantee C-compatible + array layout. + \note QList in Qt 5 did not always have a C-compatible array layout and + we often recommended to use QVector instead for more predictable + performance. This is not the case in Qt 6 anymore, where both classes + now share an implementation and can be used interchangeably. + + Here's an example of a QList that stores integers and a QList + that stores QString values: + + \snippet code/src_corelib_tools_qlist.cpp 0 + + QList stores its items in a vector (array). Typically, vectors + are created with an initial size. For example, the following code + constructs a QList with 200 elements: + + \snippet code/src_corelib_tools_qlist.cpp 1 + + The elements are automatically initialized with a + \l{default-constructed value}. If you want to initialize the + vector with a different value, pass that value as the second + argument to the constructor: + + \snippet code/src_corelib_tools_qlist.cpp 2 + + You can also call fill() at any time to fill the vector with a + value. + + QList uses 0-based indexes, just like C++ arrays. To access the + item at a particular index position, you can use operator[](). On + non-const vectors, operator[]() returns a reference to the item + that can be used on the left side of an assignment: + + \snippet code/src_corelib_tools_qlist.cpp 3 + + For read-only access, an alternative syntax is to use at(): + + \snippet code/src_corelib_tools_qlist.cpp 4 + + at() can be faster than operator[](), because it never causes a + \l{deep copy} to occur. + + Another way to access the data stored in a QList is to call + data(). The function returns a pointer to the first item in the + vector. You can use the pointer to directly access and modify the + elements stored in the vector. The pointer is also useful if you + need to pass a QList to a function that accepts a plain C++ + array. + + If you want to find all occurrences of a particular value in a + vector, use indexOf() or lastIndexOf(). The former searches + forward starting from a given index position, the latter searches + backward. Both return the index of the matching item if they found + one; otherwise, they return -1. For example: + + \snippet code/src_corelib_tools_qlist.cpp 5 + + If you simply want to check whether a vector contains a + particular value, use contains(). If you want to find out how + many times a particular value occurs in the vector, use count(). + + QList provides these basic functions to add, move, and remove + items: insert(), replace(), remove(), prepend(), append(). With + the exception of append() and replace(), these functions can be slow + (\l{linear time}) for large vectors, because they require moving many + items in the vector by one position in memory. If you want a container + class that provides fast insertion/removal in the middle, use + std::list instead. + + Unlike plain C++ arrays, QLists can be resized at any time by + calling resize(). If the new size is larger than the old size, + QList might need to reallocate the whole vector. QList tries + to reduce the number of reallocations by preallocating up to twice + as much memory as the actual data needs. + + If you know in advance approximately how many items the QList + will contain, you can call reserve(), asking QList to + preallocate a certain amount of memory. You can also call + capacity() to find out how much memory QList actually + allocated. + + Note that using non-const operators and functions can cause + QList to do a deep copy of the data. This is due to \l{implicit sharing}. + + QList's value type must be an \l{assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value; instead, + store a QWidget *. A few functions have additional requirements; + for example, indexOf() and lastIndexOf() expect the value type to + support \c operator==(). These requirements are documented on a + per-function basis. + + Like the other container classes, QList provides \l{Java-style + iterators} (QListIterator and QMutableVectorIterator) and + \l{STL-style iterators} (QList::const_iterator and + QList::iterator). In practice, these are rarely used, because + you can use indexes into the QList. + + In addition to QList, Qt also provides QVarLengthArray, a very + low-level class with little functionality that is optimized for + speed. + + QList does \e not support inserting, prepending, appending or replacing + with references to its own values. Doing so will cause your application to + abort with an error message. + + \section2 More Information on Using Qt Containers + + For a detailed discussion comparing Qt containers with each other and + with STL containers, see \l {Understand the Qt Containers}. + + \section1 Maximum size and out-of-memory conditions + + The current version of QList is limited to just under 2 GB (2^31 bytes) + in size. The exact value is architecture-dependent, since it depends on the + overhead required for managing the data block, but is no more than 32 + bytes. The number of elements that can be stored in a QList is that size + divided by the size of each element. + + In case memory allocation fails, QList will use the \l Q_CHECK_PTR macro, + which will throw a \c std::bad_alloc exception if the application is being + compiled with exception support. If exceptions are disabled, then running + out of memory is undefined behavior. + + Note that the operating system may impose further limits on applications + holding a lot of allocated memory, especially large, contiguous blocks. + Such considerations, the configuration of such behavior or any mitigation + are outside the scope of the Qt API. +*/ + +/*! + \fn template QList QList::mid(int pos, int length = -1) const + + Returns a sub-vector which contains elements from this vector, + starting at position \a pos. If \a length is -1 (the default), all + elements after \a pos are included; otherwise \a length elements (or + all remaining elements if there are less than \a length elements) + are included. +*/ + + +/*! \fn template QList::QList() + + Constructs an empty vector. + + \sa resize() +*/ + +/*! + \fn template QList::QList(QList &&other) + + Move-constructs a QList instance, making it point at the same + object that \a other was pointing to. + + \since 5.2 +*/ + +/*! \fn template QList::QList(int size) + + Constructs a vector with an initial size of \a size elements. + + The elements are initialized with a \l{default-constructed + value}. + + \sa resize() +*/ + +/*! \fn template QList::QList(int size, const T &value) + + Constructs a vector with an initial size of \a size elements. + Each element is initialized with \a value. + + \sa resize(), fill() +*/ + +/*! \fn template QList::QList(const QList &other) + + Constructs a copy of \a other. + + This operation takes \l{Algorithmic Complexity}{constant time}, + because QList is \l{implicitly shared}. This makes returning + a QList from a function very fast. If a shared instance is + modified, it will be copied (copy-on-write), and that takes + \l{Algorithmic Complexity}{linear time}. + + \sa operator=() +*/ + +/*! \fn template QList::QList(std::initializer_list args) + \since 4.8 + + Constructs a vector from the std::initializer_list given by \a args. + + This constructor is only enabled if the compiler supports C++11 initializer + lists. +*/ + +/*! \fn template template QList::QList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a vector with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + +/*! + \fn template QList::QList(QArrayDataPointerRef ref) + \internal +*/ + +/*! \fn template QList::~QList() + + Destroys the list. +*/ + +/*! \fn template QList &QList::operator=(const QList &other) + + Assigns \a other to this vector and returns a reference to this + vector. +*/ + +/*! + \fn template QList &QList::operator=(QList &&other) + + Move-assigns \a other to this QList instance. + + \since 5.2 +*/ + +/*! + \fn template QList &QList::operator=(std::initializer_list args) + + Assigns the collection of values in \a args to this QList instance. + + This operator is only enabled if the compiler supports C++11 initializer + lists. + + \since 5.14 +*/ + +/*! \fn template void QList::swap(QList &other) + \since 4.8 + + Swaps vector \a other with this vector. This operation is very fast and + never fails. +*/ + +/*! \fn template void QList::swapItemsAt(int i, int j) + \since 5.14 + + Exchange the item at index position \a i with the item at index + position \a j. This function assumes that both \a i and \a j are + at least 0 but less than size(). To avoid failure, test that both + \a i and \a j are at least 0 and less than size(). +*/ + + +/*! \fn template bool QList::operator==(const QList &other) const + + Returns \c true if \a other is equal to this vector; otherwise + returns \c false. + + Two vectors are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator!=() +*/ + +/*! \fn template bool QList::operator!=(const QList &other) const + + Returns \c true if \a other is not equal to this vector; otherwise + returns \c false. + + Two vectors are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator==() +*/ + +/*! \fn template bool operator<(const QList &lhs, const QList &rhs) + \since 5.6 + \relates QList + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn template bool operator<=(const QList &lhs, const QList &rhs) + \since 5.6 + \relates QList + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically less than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn template bool operator>(const QList &lhs, const QList &rhs) + \since 5.6 + \relates QList + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! \fn template bool operator>=(const QList &lhs, const QList &rhs) + \since 5.6 + \relates QList + + Returns \c true if vector \a lhs is + \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} + {lexicographically greater than or equal to} \a rhs; otherwise returns \c false. + + This function requires the value type to have an implementation + of \c operator<(). +*/ + +/*! + \fn template size_t qHash(const QList &key, size_t seed = 0) + \since 5.6 + \relates QList + + Returns the hash value for \a key, + using \a seed to seed the calculation. + + This function requires qHash() to be overloaded for the value type \c T. +*/ + +/*! \fn template int QList::size() const + + Returns the number of items in the vector. + + \sa isEmpty(), resize() +*/ + +/*! \fn template bool QList::isEmpty() const + + Returns \c true if the vector has size 0; otherwise returns \c false. + + \sa size(), resize() +*/ + +/*! \fn template void QList::resize(int size) + + Sets the size of the vector to \a size. If \a size is greater than the + current size, elements are added to the end; the new elements are + initialized with a \l{default-constructed value}. If \a size is less + than the current size, elements are removed from the end. + + Since Qt 5.6, resize() doesn't shrink the capacity anymore. + To shed excess capacity, use squeeze(). + + \sa size() +*/ + +/*! \fn template int QList::capacity() const + + Returns the maximum number of items that can be stored in the + vector without forcing a reallocation. + + The sole purpose of this function is to provide a means of fine + tuning QList's memory usage. In general, you will rarely ever + need to call this function. If you want to know how many items are + in the vector, call size(). + + \note a statically allocated vector will report a capacity of 0, + even if it's not empty. + + \sa reserve(), squeeze() +*/ + +/*! \fn template void QList::reserve(int size) + + Attempts to allocate memory for at least \a size elements. If you + know in advance how large the vector will be, you should call this + function to prevent reallocations and memory fragmentation. + + If \a size is an underestimate, the worst that will happen is that + the QList will be a bit slower. If \a size is an overestimate, you + may have used more memory than the normal QList growth strategy + would have allocated—or you may have used less. + + An alternative to reserve() is calling resize(). Whether or not that is + faster than reserve() depends on the element type, because resize() + default-constructs all elements, and requires assignment to existing + entries rather than calling append(), which copy- or move-constructs. + For simple types, like \c int or \c double, resize() is typically faster, + but for anything more complex, you should prefer reserve(). + + \warning If the size passed to resize() was underestimated, you run out + of allocated space and into undefined behavior. This problem does not + exist with reserve(), because it treats the size as just a hint. + + \sa squeeze(), capacity() +*/ + +/*! \fn template void QList::squeeze() + + Releases any memory not required to store the items. + + The sole purpose of this function is to provide a means of fine + tuning QList's memory usage. In general, you will rarely ever + need to call this function. + + \sa reserve(), capacity() +*/ + +/*! \fn template void QList::detach() + + \internal +*/ + +/*! \fn template bool QList::isDetached() const + + \internal +*/ + +/*! \fn template void QList::setSharable(bool sharable) + + \internal +*/ + +/*! \fn template bool QList::isSharedWith(const QList &other) const + + \internal +*/ + +/*! \fn template T *QList::data() + + Returns a pointer to the data stored in the vector. The pointer + can be used to access and modify the items in the vector. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 6 + + The pointer remains valid as long as the vector isn't + reallocated. + + This function is mostly useful to pass a vector to a function + that accepts a plain C++ array. + + \sa constData(), operator[]() +*/ + +/*! \fn template const T *QList::data() const + + \overload +*/ + +/*! \fn template const T *QList::constData() const + + Returns a const pointer to the data stored in the vector. The + pointer can be used to access the items in the vector. + The pointer remains valid as long as the vector isn't + reallocated. + + This function is mostly useful to pass a vector to a function + that accepts a plain C++ array. + + \sa data(), operator[]() +*/ + +/*! \fn template void QList::clear() + + Removes all the elements from the vector. + + \note Until Qt 5.6, this also released the memory used by + the vector. From Qt 5.7, the capacity is preserved. To shed + all capacity, swap with a default-constructed vector: + \code + QList v ...; + QList().swap(v); + Q_ASSERT(v.capacity() == 0); + \endcode + or call squeeze(). + + \sa squeeze() +*/ + +/*! \fn template const T &QList::at(int i) const + + Returns the item at index position \a i in the vector. + + \a i must be a valid index position in the vector (i.e., 0 <= \a + i < size()). + + \sa value(), operator[]() +*/ + +/*! \fn template T &QList::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. + + \a i must be a valid index position in the vector (i.e., 0 <= \a i + < size()). + + Note that using non-const operators can cause QList to do a deep + copy. + + \sa at(), value() +*/ + +/*! \fn template const T &QList::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! + \fn template void QList::append(const T &value) + + Inserts \a value at the end of the vector. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 7 + + This is the same as calling resize(size() + 1) and assigning \a + value to the new last element in the vector. + + This operation is relatively fast, because QList typically + allocates more memory than necessary, so it can grow without + reallocating the entire vector each time. + + \sa operator<<(), prepend(), insert() +*/ + +/*! + \fn template void QList::append(T &&value) + \since 5.6 + + \overload + + Example: + \snippet code/src_corelib_tools_qlist.cpp move-append +*/ + +/*! \fn template void QList::append(const QList &value) + + \overload + + \since 5.5 + + Appends the items of the \a value vector to this vector. + + \sa operator<<(), operator+=() +*/ + + +/*! + \fn template void QList::prepend(const T &value) + \fn template void QList::prepend(T &&value) + + Inserts \a value at the beginning of the vector. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 8 + + This is the same as vector.insert(0, \a value). + + For large vectors, this operation can be slow (\l{linear time}), + because it requires moving all the items in the vector by one + position further in memory. If you want a container class that + provides a fast prepend operation, use std::list + instead. + + \sa append(), insert() +*/ + +/*! + \fn template template T &QList::emplaceBack(Args&&... args) + \fn template template T &QList::emplace_back(Args&&... args) + + Adds a new element to the end for the container. This new element + is constructed in-place using \a args as the arguments for its + construction. + + Returns a reference to the new element. + + Example: + \snippet code/src_corelib_tools_qlist.cpp emplace-back + + It is also possible to access a newly created object by using + returned reference: + \snippet code/src_corelib_tools_qlist.cpp emplace-back-ref + + This is the same as vector.emplace(vector.size(), \a args). + + \sa emplace +*/ + +/*! \fn template void QList::insert(int i, const T &value) + \fn template void QList::insert(int i, T &&value) + + Inserts \a value at index position \a i in the vector. If \a i is + 0, the value is prepended to the vector. If \a i is size(), the + value is appended to the vector. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 9 + + For large vectors, this operation can be slow (\l{linear time}), + because it requires moving all the items at indexes \a i and + above by one position further in memory. If you want a container + class that provides a fast insert() function, use std::list + instead. + + \sa append(), prepend(), remove() +*/ + +/*! \fn template void QList::insert(int i, int count, const T &value) + + \overload + + Inserts \a count copies of \a value at index position \a i in the + vector. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 10 +*/ + +/*! + \fn template QList::iterator QList::insert(iterator before, const T &value) + \fn template QList::iterator QList::insert(iterator before, T &&value) + + \overload + + Inserts \a value in front of the item pointed to by the iterator + \a before. Returns an iterator pointing at the inserted item. +*/ + +/*! \fn template QList::iterator QList::insert(iterator before, int count, const T &value) + + Inserts \a count copies of \a value in front of the item pointed to + by the iterator \a before. Returns an iterator pointing at the + first of the inserted items. +*/ + +/*! + \fn template template QList::iterator QList::emplace(int i, Args&&... args) + + Extends the container by inserting a new element at position \a i. + This new element is constructed in-place using \a args as the + arguments for its construction. + + Returns an iterator to the new element. + + Example: + \snippet code/src_corelib_tools_qlist.cpp emplace + + \note It is garanteed that the element will be created in place + at the beginning, but after that it might be copied or + moved to the right position. + + \sa emplaceBack +*/ + + +/*! \fn template void QList::replace(int i, const T &value) + + Replaces the item at index position \a i with \a value. + + \a i must be a valid index position in the vector (i.e., 0 <= \a + i < size()). + + \sa operator[](), remove() +*/ + +/*! \fn template void QList::remove(int i) + + \overload + + Removes the element at index position \a i. + + \sa insert(), replace(), fill() +*/ + +/*! \fn template void QList::remove(int i, int count) + + \overload + + Removes \a count elements from the middle of the vector, starting at + index position \a i. + + \sa insert(), replace(), fill() +*/ + +/*! \fn template void QList::removeAt(int i) + \since 5.2 + + Removes the element at index position \a i. + Equivalent to + \code + remove(i); + \endcode + + Provided for compatibility with QList. + + \sa remove(), QList::removeAt() +*/ + +/*! \fn template int QList::removeAll(const T &t) + \since 5.4 + + Removes all elements that compare equal to \a t from the + vector. Returns the number of elements removed, if any. + + Provided for compatibility with QList. + + \sa removeOne(), QList::removeAll() +*/ + +/*! \fn template bool QList::removeOne(const T &t) + \since 5.4 + + Removes the first element that compares equal to \a t from the + vector. Returns whether an element was, in fact, removed. + + Provided for compatibility with QList. + + \sa removeAll(), QList::removeOne() +*/ + +/*! \fn template int QList::length() const + \since 5.2 + + Same as size() and count(). + + Provided for compatibility with QList. + + \sa size(), count(), QList::length() +*/ + +/*! \fn template T QList::takeAt(int i) + \since 5.2 + + Removes the element at index position \a i and returns it. + + Equivalent to + \code + T t = at(i); + remove(i); + return t; + \endcode + + Provided for compatibility with QList. + + \sa takeFirst(), takeLast(), QList::takeAt() +*/ + +/*! \fn template void QList::move(int from, int to) + \since 5.6 + + Moves the item at index position \a from to index position \a to. + + Provided for compatibility with QList. + + \sa QList::move() +*/ + +/*! \fn template void QList::removeFirst() + \since 5.1 + Removes the first item in the vector. Calling this function is + equivalent to calling remove(0). The vector must not be empty. If + the vector can be empty, call isEmpty() before calling this + function. + + \sa remove(), takeFirst(), isEmpty() +*/ + +/*! \fn template void QList::removeLast() + \since 5.1 + Removes the last item in the vector. Calling this function is + equivalent to calling remove(size() - 1). The vector must not be + empty. If the vector can be empty, call isEmpty() before calling + this function. + + \sa remove(), takeLast(), removeFirst(), isEmpty() +*/ + +/*! \fn template T QList::takeFirst() + \since 5.1 + + Removes the first item in the vector and returns it. This function + assumes the vector is not empty. To avoid failure, call isEmpty() + before calling this function. + + \sa takeLast(), removeFirst() +*/ + +/*! \fn template T QList::takeLast() + \since 5.1 + + Removes the last item in the list and returns it. This function + assumes the vector is not empty. To avoid failure, call isEmpty() + before calling this function. + + If you don't use the return value, removeLast() is more + efficient. + + \sa takeFirst(), removeLast() +*/ + +/*! + \fn template template QList::iterator QList::emplace(QList::iterator before, Args&&... args) + + \overload + + Creates a new element in front of the item pointed to by the + iterator \a before. This new element is constructed in-place + using \a args as the arguments for its construction. + + Returns an iterator to the new element. +*/ + +/*! \fn template QList &QList::fill(const T &value, int size = -1) + + Assigns \a value to all items in the vector. If \a size is + different from -1 (the default), the vector is resized to size \a + size beforehand. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 11 + + \sa resize() +*/ + +/*! \fn template int QList::indexOf(const T &value, int from = 0) const + + Returns the index position of the first occurrence of \a value in + the vector, searching forward from index position \a from. + Returns -1 if no item matched. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 12 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa lastIndexOf(), contains() +*/ + +/*! \fn template int QList::lastIndexOf(const T &value, int from = -1) const + + Returns the index position of the last occurrence of the value \a + value in the vector, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last item. Returns -1 if no item matched. + + Example: + \snippet code/src_corelib_tools_qlist.cpp 13 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf() +*/ + +/*! \fn template bool QList::contains(const T &value) const + + Returns \c true if the vector contains an occurrence of \a value; + otherwise returns \c false. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf(), count() +*/ + +/*! \fn template bool QList::startsWith(const T &value) const + \since 4.5 + + Returns \c true if this vector is not empty and its first + item is equal to \a value; otherwise returns \c false. + + \sa isEmpty(), first() +*/ + +/*! \fn template bool QList::endsWith(const T &value) const + \since 4.5 + + Returns \c true if this vector is not empty and its last + item is equal to \a value; otherwise returns \c false. + + \sa isEmpty(), last() +*/ + + +/*! \fn template int QList::count(const T &value) const + + Returns the number of occurrences of \a value in the vector. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa contains(), indexOf() +*/ + +/*! \fn template int QList::count() const + + \overload + + Same as size(). +*/ + +/*! \fn template QList::iterator QList::begin() + + Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in + the vector. + + \sa constBegin(), end() +*/ + +/*! \fn template QList::const_iterator QList::begin() const + + \overload +*/ + +/*! \fn template QList::const_iterator QList::cbegin() const + \since 5.0 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item + in the vector. + + \sa begin(), cend() +*/ + +/*! \fn template QList::const_iterator QList::constBegin() const + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item + in the vector. + + \sa begin(), constEnd() +*/ + +/*! \fn template QList::iterator QList::end() + + Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item + after the last item in the vector. + + \sa begin(), constEnd() +*/ + +/*! \fn template QList::const_iterator QList::end() const + + \overload +*/ + +/*! \fn template QList::const_iterator QList::cend() const + \since 5.0 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last item in the vector. + + \sa cbegin(), end() +*/ + +/*! \fn template QList::const_iterator QList::constEnd() const + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last item in the vector. + + \sa constBegin(), end() +*/ + +/*! \fn template QList::reverse_iterator QList::rbegin() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the vector, in reverse order. + + \sa begin(), crbegin(), rend() +*/ + +/*! \fn template QList::const_reverse_iterator QList::rbegin() const + \since 5.6 + \overload +*/ + +/*! \fn template QList::const_reverse_iterator QList::crbegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first + item in the vector, in reverse order. + + \sa begin(), rbegin(), rend() +*/ + +/*! \fn template QList::reverse_iterator QList::rend() + \since 5.6 + + Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past + the last item in the vector, in reverse order. + + \sa end(), crend(), rbegin() +*/ + +/*! \fn template QList::const_reverse_iterator QList::rend() const + \since 5.6 + \overload +*/ + +/*! \fn template QList::const_reverse_iterator QList::crend() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one + past the last item in the vector, in reverse order. + + \sa end(), rend(), rbegin() +*/ + +/*! \fn template QList::iterator QList::erase(iterator pos) + + Removes the item pointed to by the iterator \a pos from the + vector, and returns an iterator to the next item in the vector + (which may be end()). + + \sa insert(), remove() +*/ + +/*! \fn template QList::iterator QList::erase(iterator begin, iterator end) + + \overload + + Removes all the items from \a begin up to (but not including) \a + end. Returns an iterator to the same item that \a end referred to + before the call. +*/ + +/*! \fn template T& QList::first() + + Returns a reference to the first item in the vector. This + function assumes that the vector isn't empty. + + \sa last(), isEmpty(), constFirst() +*/ + +/*! \fn template const T& QList::first() const + + \overload +*/ + +/*! \fn template const T& QList::constFirst() const + \since 5.6 + + Returns a const reference to the first item in the vector. This + function assumes that the vector isn't empty. + + \sa constLast(), isEmpty(), first() +*/ + +/*! \fn template T& QList::last() + + Returns a reference to the last item in the vector. This function + assumes that the vector isn't empty. + + \sa first(), isEmpty(), constLast() +*/ + +/*! \fn template const T& QList::last() const + + \overload +*/ + +/*! \fn template const T& QList::constLast() const + \since 5.6 + + Returns a const reference to the last item in the vector. This function + assumes that the vector isn't empty. + + \sa constFirst(), isEmpty(), last() +*/ + +/*! \fn template T QList::value(int i) const + + Returns the value at index position \a i in the vector. + + If the index \a i is out of bounds, the function returns + a \l{default-constructed value}. If you are certain that + \a i is within bounds, you can use at() instead, which is slightly + faster. + + \sa at(), operator[]() +*/ + +/*! \fn template T QList::value(int i, const T &defaultValue) const + + \overload + + If the index \a i is out of bounds, the function returns + \a defaultValue. +*/ + +/*! \fn template void QList::push_back(const T &value) + + This function is provided for STL compatibility. It is equivalent + to append(\a value). +*/ + +/*! \fn template void QList::push_back(T &&value) + \since 5.6 + \overload +*/ + +/*! + \fn template void QList::push_front(const T &value) + \fn template void QList::push_front(T &&value) + + This function is provided for STL compatibility. It is equivalent + to prepend(\a value). +*/ + +/*! \fn template void QList::pop_front() + + This function is provided for STL compatibility. It is equivalent + to removeFirst(). +*/ + +/*! \fn template void QList::pop_back() + + This function is provided for STL compatibility. It is equivalent + to removeLast(). +*/ + +/*! \fn template T& QList::front() + + This function is provided for STL compatibility. It is equivalent + to first(). +*/ + +/*! \fn template QList::const_reference QList::front() const + + \overload +*/ + +/*! \fn template QList::reference QList::back() + + This function is provided for STL compatibility. It is equivalent + to last(). +*/ + +/*! \fn template QList::const_reference QList::back() const + + \overload +*/ + +/*! \fn template void QList::shrink_to_fit() + \since 5.10 + + This function is provided for STL compatibility. It is equivalent + to squeeze(). +*/ + +/*! \fn template bool QList::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty(), returning \c true if the vector is empty; otherwise + returns \c false. +*/ + +/*! \fn template QList &QList::operator+=(const QList &other) + + Appends the items of the \a other vector to this vector and + returns a reference to this vector. + + \sa operator+(), append() +*/ + +/*! \fn template void QList::operator+=(const T &value) + + \overload + + Appends \a value to the vector. + + \sa append(), operator<<() +*/ + +/*! \fn template void QList::operator+=(T &&value) + \since 5.11 + + \overload + + \sa append(), operator<<() +*/ + +/*! \fn template QList QList::operator+(const QList &other) const + + Returns a vector that contains all the items in this vector + followed by all the items in the \a other vector. + + \sa operator+=() +*/ + +/*! \fn template QList &QList::operator<<(const T &value) + + Appends \a value to the vector and returns a reference to this + vector. + + \sa append(), operator+=() +*/ + +/*! \fn template QList &QList::operator<<(T &&value) + \since 5.11 + + \overload + + \sa append(), operator+=() +*/ + + +/*! \fn template QList &QList::operator<<(const QList &other) + + Appends \a other to the vector and returns a reference to the + vector. +*/ + +/*! \typedef QList::iterator + + The QList::iterator typedef provides an STL-style non-const + iterator for QList and QStack. + + QList provides both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style non-const iterator is simply a typedef + for "T *" (pointer to T). + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::begin(), QList::end(), QList::const_iterator, QMutableVectorIterator +*/ + +/*! \typedef QList::const_iterator + + The QList::const_iterator typedef provides an STL-style const + iterator for QList and QStack. + + QList provides both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style const iterator is simply a typedef for + "const T *" (pointer to const T). + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::constBegin(), QList::constEnd(), QList::iterator, QListIterator +*/ + +/*! \typedef QList::reverse_iterator + \since 5.6 + + The QList::reverse_iterator typedef provides an STL-style non-const + reverse iterator for QList. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::rbegin(), QList::rend(), QList::const_reverse_iterator, QList::iterator +*/ + +/*! \typedef QList::const_reverse_iterator + \since 5.6 + + The QList::const_reverse_iterator typedef provides an STL-style const + reverse iterator for QList. + + It is simply a typedef for \c{std::reverse_iterator}. + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QList::rbegin(), QList::rend(), QList::reverse_iterator, QList::const_iterator +*/ + +/*! \typedef QList::Iterator + + Qt-style synonym for QList::iterator. +*/ + +/*! \typedef QList::ConstIterator + + Qt-style synonym for QList::const_iterator. +*/ + +/*! \typedef QList::const_pointer + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! \typedef QList::const_reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! \typedef QList::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! \typedef QList::pointer + + Typedef for T *. Provided for STL compatibility. +*/ + +/*! \typedef QList::reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! \typedef QList::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! \typedef QList::value_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! \fn template QList QList::toList() const + \fn template QList QList::toVector() const + \obsolete + + A no-op in Qt 6. Provided for backwards compatibility with + Qt 5, where QList and QVector where two different types. + + Returns this list. +*/ + +/*! \fn template QList QList::fromList(const QList &list) + \fn template QList QList::fromVector(const QList &list) + \obsolete + + A no-op in Qt 6. Provided for backwards compatibility with + Qt 5, where QList and QVector where two different types. + + Returns this list. +*/ + +/*! \fn template QList QList::fromStdVector(const std::vector &vector) + + Returns a QList object with the data contained in \a vector. The + order of the elements in the QList is the same as in \a vector. + + Example: + + \snippet code/src_corelib_tools_qlist.cpp 16 + + \include containers-range-constructor.qdocinc + + \sa toStdVector(), QList::fromStdList() +*/ + +/*! \fn template std::vector QList::toStdVector() const + + Returns a std::vector object with the data contained in this QList. + Example: + + \snippet code/src_corelib_tools_qlist.cpp 17 + + \include containers-range-constructor.qdocinc + + \sa fromStdVector(), QList::toStdList() +*/ + +/*! \fn template QDataStream &operator<<(QDataStream &out, const QList &vector) + \relates QList + + Writes the vector \a vector to stream \a out. + + This function requires the value type to implement \c operator<<(). + + \sa{Serializing Qt Data Types}{Format of the QDataStream operators} +*/ + +/*! \fn template QDataStream &operator>>(QDataStream &in, QList &vector) + \relates QList + + Reads a vector from stream \a in into \a vector. + + This function requires the value type to implement \c operator>>(). + + \sa{Serializing Qt Data Types}{Format of the QDataStream operators} +*/ diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index b502a86442..8d880407dd 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2019 Intel Corporation +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -41,758 +40,18 @@ #ifndef QVECTOR_H #define QVECTOR_H -#include -#include -#include -#include - -#include -#include -#include -#include +#include +#include QT_BEGIN_NAMESPACE -namespace QtPrivate { - template int indexOf(const QVector &list, const U &u, int from); - template int lastIndexOf(const QVector &list, const U &u, int from); -} - -template struct QVectorSpecialMethods -{ -protected: - ~QVectorSpecialMethods() = default; -}; -template <> struct QVectorSpecialMethods; -template <> struct QVectorSpecialMethods; - -template -class QVector -#ifndef Q_QDOC - : public QVectorSpecialMethods -#endif -{ - typedef QTypedArrayData Data; - typedef QArrayDataOps DataOps; - typedef QArrayDataPointer DataPointer; - class DisableRValueRefs {}; - - DataPointer d; - - template friend int QtPrivate::indexOf(const QVector &list, const U &u, int from); - template friend int QtPrivate::lastIndexOf(const QVector &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 reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef typename DataPointer::parameter_type parameter_type; - using rvalue_ref = typename std::conditional::type; - -private: - void resize_internal(int i, Qt::Initialization); - bool isValidIterator(const_iterator i) const - { - const std::less less = {}; - return !less(d->end(), i) && !less(i, d->begin()); - } -public: - QVector(DataPointer dd) noexcept - : d(dd) - { - } - -public: - constexpr inline QVector() noexcept { } - explicit QVector(int size) - : d(Data::allocate(size)) - { - if (size) - d->appendInitialize(size); - } - QVector(int size, const T &t) - : d(Data::allocate(size)) - { - if (size) - d->copyAppend(size, t); - } - - inline QVector(const QVector &other) noexcept : d(other.d) {} - QVector(QVector &&other) noexcept : d(std::move(other.d)) {} - inline QVector(std::initializer_list args) - : d(Data::allocate(args.size())) - { - if (args.size()) - d->copyAppend(args.begin(), args.end()); - } - - ~QVector() /*noexcept(std::is_nothrow_destructible::value)*/ {} - QVector &operator=(const QVector &other) { d = other.d; return *this; } - QVector &operator=(QVector &&other) noexcept(std::is_nothrow_destructible::value) - { - d = std::move(other.d); - return *this; - } - QVector &operator=(std::initializer_list args) - { - d = DataPointer(Data::allocate(args.size())); - if (args.size()) - d->copyAppend(args.begin(), args.end()); - return *this; - } - template = true> - QVector(InputIterator i1, InputIterator i2) - : d(Data::allocate(std::distance(i1, i2))) - { - if (std::distance(i1, i2)) - d->copyAppend(i1, i2); - } - - template = true> - QVector(InputIterator i1, InputIterator i2) - : QVector() - { - QtPrivate::reserveIfForwardIterator(this, i1, i2); - std::copy(i1, i2, std::back_inserter(*this)); - } - - void swap(QVector &other) noexcept { qSwap(d, other.d); } - - friend bool operator==(const QVector &l, const QVector &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 QVector &l, const QVector &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 QVector &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), "QVector::at", "index out of range"); - return data()[i]; - } - reference operator[](int i) - { - Q_ASSERT_X(size_t(i) < size_t(d->size), "QVector::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 QVector &l) { append(l.constBegin(), l.constEnd()); } - void prepend(rvalue_ref t); - void prepend(const T &t); - - template - reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward(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), "QVector::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), "QVector::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), "QVector::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 - iterator emplace(const_iterator before, Args&&... args) - { - Q_ASSERT_X(isValidIterator(before), "QVector::emplace", "The specified iterator argument 'before' is invalid"); - return emplace(std::distance(constBegin(), before), std::forward(args)...); - } - - template - 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 ilist ); -#endif - void replace(int i, const T &t) - { - Q_ASSERT_X(i >= 0 && i < d->size, "QVector::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, "QVector::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; } - - QVector &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(), "QVector::move(int,int)", "'from' is out-of-range"); - Q_ASSERT_X(to >= 0 && to < size(), "QVector::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; } - QVector 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(), - "QVector::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 - reference emplace_back(Args&&... args) { return emplaceBack(std::forward(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 - QVector &operator+=(const QVector &l) { append(l.cbegin(), l.cend()); return *this; } - inline QVector operator+(const QVector &l) const - { QVector n = *this; n += l; return n; } - inline QVector &operator+=(const T &t) - { append(t); return *this; } - inline QVector &operator<< (const T &t) - { append(t); return *this; } - inline QVector &operator<<(const QVector &l) - { *this += l; return *this; } - inline QVector &operator+=(rvalue_ref t) - { append(std::move(t)); return *this; } - inline QVector &operator<<(rvalue_ref t) - { append(std::move(t)); return *this; } - - // Consider deprecating in 6.4 or later - static QVector fromList(const QVector &list) { return list; } - QVector toList() const { return *this; } - - static inline QVector fromVector(const QVector &vector) { return vector; } - inline QVector toVector() const { return *this; } -}; - -#if defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201606 -template ::value_type, - QtPrivate::IfIsInputIterator = true> -QVector(InputIterator, InputIterator) -> QVector; -#endif - -template -inline void QVector::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 -void QVector::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 -inline void QVector::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 -inline void QVector::remove(int i, int n) -{ - Q_ASSERT_X(size_t(i) + size_t(n) <= size_t(d->size), "QVector::remove", "index out of range"); - Q_ASSERT_X(n >= 0, "QVector::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 -inline void QVector::prepend(const T &t) -{ insert(0, 1, t); } -template -void QVector::prepend(rvalue_ref t) -{ insert(0, std::move(t)); } - +#if !defined(QT_NO_JAVA_STYLE_ITERATORS) template -inline T QVector::value(int i, const T &defaultValue) const -{ - return size_t(i) < size_t(d->size) ? at(i) : defaultValue; -} - -template -inline void QVector::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 -inline typename QVector::iterator -QVector::insert(int i, int n, parameter_type t) -{ - Q_ASSERT_X(size_t(i) <= size_t(d->size), "QVector::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 -template -typename QVector::iterator -QVector::emplace(int i, Args&&... args) -{ - Q_ASSERT_X(i >= 0 && i <= d->size, "QVector::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)...); - - // 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)...); - } - return d.begin() + i; -} - -template -typename QVector::iterator QVector::erase(const_iterator abegin, const_iterator aend) -{ - Q_ASSERT_X(isValidIterator(abegin), "QVector::erase", "The specified iterator argument 'abegin' is invalid"); - Q_ASSERT_X(isValidIterator(aend), "QVector::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 -inline QVector &QVector::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 -int indexOf(const QVector &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 -int lastIndexOf(const QVector &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 -int QVector::indexOf(const T &t, int from) const noexcept -{ - return QtPrivate::indexOf(*this, t, from); -} - -template -int QVector::lastIndexOf(const T &t, int from) const noexcept -{ - return QtPrivate::lastIndexOf(*this, t, from); -} - -template -inline QVector QVector::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 QVector(); - 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(Vector) -Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector) - -template -size_t qHash(const QVector &key, size_t seed = 0) - noexcept(noexcept(qHashRange(key.cbegin(), key.cend(), seed))) -{ - return qHashRange(key.cbegin(), key.cend(), seed); -} - -template -auto operator<(const QVector &lhs, const QVector &rhs) - noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end()))) - -> decltype(std::declval() < std::declval()) -{ - return std::lexicographical_compare(lhs.begin(), lhs.end(), - rhs.begin(), rhs.end()); -} - -template -auto operator>(const QVector &lhs, const QVector &rhs) - noexcept(noexcept(lhs < rhs)) - -> decltype(lhs < rhs) -{ - return rhs < lhs; -} - -template -auto operator<=(const QVector &lhs, const QVector &rhs) - noexcept(noexcept(lhs < rhs)) - -> decltype(lhs < rhs) -{ - return !(lhs > rhs); -} - -template -auto operator>=(const QVector &lhs, const QVector &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 QVector and - ### QVector respectively. -*/ - -#if defined(Q_CC_MSVC) && !defined(QT_BUILD_CORE_LIB) -QT_BEGIN_INCLUDE_NAMESPACE -#include -QT_END_INCLUDE_NAMESPACE -extern template class Q_CORE_EXPORT QVector; -extern template class Q_CORE_EXPORT QVector; +using QMutableVectorIterator = QMutableListIterator; +template +using QVectorIterator = QListIterator; #endif -QVector QStringView::toUcs4() const { return QtPrivate::convertToUcs4(*this); } - QT_END_NAMESPACE -#include -#include - #endif // QVECTOR_H diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc deleted file mode 100644 index 88baaab8c1..0000000000 --- a/src/corelib/tools/qvector.qdoc +++ /dev/null @@ -1,1473 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QVector - \inmodule QtCore - \brief The QVector class is a template class that provides a dynamic array. - - \ingroup tools - \ingroup shared - - \reentrant - - QVector\ is one of Qt's generic \l{container classes}. It - stores its items in adjacent memory locations and provides fast - index-based access. - - QList\, QVector\, and QVarLengthArray\ - provide similar APIs and functionality. They are often interchangeable, - but there are performance consequences. Here is an overview of use cases: - - \list - \li QVector should be your default first choice. - QVector\ will usually give better performance than QList\, - because QVector\ always stores its items sequentially in memory, - where QList\ will allocate its items on the heap unless - \c {sizeof(T) <= sizeof(void*)} and T has been declared to be - either a \c{Q_MOVABLE_TYPE} or a \c{Q_PRIMITIVE_TYPE} using - \l {Q_DECLARE_TYPEINFO}. See the \l {Pros and Cons of Using QList} - for an explanation. - \li However, QList is used throughout the Qt APIs for passing - parameters and for returning values. Use QList to interface with - those APIs. - \li If you need a real linked list, which guarantees - \l{Algorithmic Complexity}{constant time} insertions mid-list and - uses iterators to items rather than indexes, use std::list. - \endlist - - \note QVector and QVarLengthArray both guarantee C-compatible - array layout. QList does not. This might be important if your - application must interface with a C API. - - Here's an example of a QVector that stores integers and a QVector - that stores QString values: - - \snippet code/src_corelib_tools_qvector.cpp 0 - - QVector stores its items in a vector (array). Typically, vectors - are created with an initial size. For example, the following code - constructs a QVector with 200 elements: - - \snippet code/src_corelib_tools_qvector.cpp 1 - - The elements are automatically initialized with a - \l{default-constructed value}. If you want to initialize the - vector with a different value, pass that value as the second - argument to the constructor: - - \snippet code/src_corelib_tools_qvector.cpp 2 - - You can also call fill() at any time to fill the vector with a - value. - - QVector uses 0-based indexes, just like C++ arrays. To access the - item at a particular index position, you can use operator[](). On - non-const vectors, operator[]() returns a reference to the item - that can be used on the left side of an assignment: - - \snippet code/src_corelib_tools_qvector.cpp 3 - - For read-only access, an alternative syntax is to use at(): - - \snippet code/src_corelib_tools_qvector.cpp 4 - - at() can be faster than operator[](), because it never causes a - \l{deep copy} to occur. - - Another way to access the data stored in a QVector is to call - data(). The function returns a pointer to the first item in the - vector. You can use the pointer to directly access and modify the - elements stored in the vector. The pointer is also useful if you - need to pass a QVector to a function that accepts a plain C++ - array. - - If you want to find all occurrences of a particular value in a - vector, use indexOf() or lastIndexOf(). The former searches - forward starting from a given index position, the latter searches - backward. Both return the index of the matching item if they found - one; otherwise, they return -1. For example: - - \snippet code/src_corelib_tools_qvector.cpp 5 - - If you simply want to check whether a vector contains a - particular value, use contains(). If you want to find out how - many times a particular value occurs in the vector, use count(). - - QVector provides these basic functions to add, move, and remove - items: insert(), replace(), remove(), prepend(), append(). With - the exception of append() and replace(), these functions can be slow - (\l{linear time}) for large vectors, because they require moving many - items in the vector by one position in memory. If you want a container - class that provides fast insertion/removal in the middle, use - std::list instead. - - Unlike plain C++ arrays, QVectors can be resized at any time by - calling resize(). If the new size is larger than the old size, - QVector might need to reallocate the whole vector. QVector tries - to reduce the number of reallocations by preallocating up to twice - as much memory as the actual data needs. - - If you know in advance approximately how many items the QVector - will contain, you can call reserve(), asking QVector to - preallocate a certain amount of memory. You can also call - capacity() to find out how much memory QVector actually - allocated. - - Note that using non-const operators and functions can cause - QVector to do a deep copy of the data. This is due to \l{implicit sharing}. - - QVector's value type must be an \l{assignable data type}. This - covers most data types that are commonly used, but the compiler - won't let you, for example, store a QWidget as a value; instead, - store a QWidget *. A few functions have additional requirements; - for example, indexOf() and lastIndexOf() expect the value type to - support \c operator==(). These requirements are documented on a - per-function basis. - - Like the other container classes, QVector provides \l{Java-style - iterators} (QVectorIterator and QMutableVectorIterator) and - \l{STL-style iterators} (QVector::const_iterator and - QVector::iterator). In practice, these are rarely used, because - you can use indexes into the QVector. - - In addition to QVector, Qt also provides QVarLengthArray, a very - low-level class with little functionality that is optimized for - speed. - - QVector does \e not support inserting, prepending, appending or replacing - with references to its own values. Doing so will cause your application to - abort with an error message. - - \section2 More Information on Using Qt Containers - - For a detailed discussion comparing Qt containers with each other and - with STL containers, see \l {Understand the Qt Containers}. - - \section1 Maximum size and out-of-memory conditions - - The current version of QVector is limited to just under 2 GB (2^31 bytes) - in size. The exact value is architecture-dependent, since it depends on the - overhead required for managing the data block, but is no more than 32 - bytes. The number of elements that can be stored in a QVector is that size - divided by the size of each element. - - In case memory allocation fails, QVector will use the \l Q_CHECK_PTR macro, - which will throw a \c std::bad_alloc exception if the application is being - compiled with exception support. If exceptions are disabled, then running - out of memory is undefined behavior. - - Note that the operating system may impose further limits on applications - holding a lot of allocated memory, especially large, contiguous blocks. - Such considerations, the configuration of such behavior or any mitigation - are outside the scope of the Qt API. -*/ - -/*! - \fn template QVector QVector::mid(int pos, int length = -1) const - - Returns a sub-vector which contains elements from this vector, - starting at position \a pos. If \a length is -1 (the default), all - elements after \a pos are included; otherwise \a length elements (or - all remaining elements if there are less than \a length elements) - are included. -*/ - - -/*! \fn template QVector::QVector() - - Constructs an empty vector. - - \sa resize() -*/ - -/*! - \fn template QVector::QVector(QVector &&other) - - Move-constructs a QVector instance, making it point at the same - object that \a other was pointing to. - - \since 5.2 -*/ - -/*! \fn template QVector::QVector(int size) - - Constructs a vector with an initial size of \a size elements. - - The elements are initialized with a \l{default-constructed - value}. - - \sa resize() -*/ - -/*! \fn template QVector::QVector(int size, const T &value) - - Constructs a vector with an initial size of \a size elements. - Each element is initialized with \a value. - - \sa resize(), fill() -*/ - -/*! \fn template QVector::QVector(const QVector &other) - - Constructs a copy of \a other. - - This operation takes \l{Algorithmic Complexity}{constant time}, - because QVector is \l{implicitly shared}. This makes returning - a QVector from a function very fast. If a shared instance is - modified, it will be copied (copy-on-write), and that takes - \l{Algorithmic Complexity}{linear time}. - - \sa operator=() -*/ - -/*! \fn template QVector::QVector(std::initializer_list args) - \since 4.8 - - Constructs a vector from the std::initializer_list given by \a args. - - This constructor is only enabled if the compiler supports C++11 initializer - lists. -*/ - -/*! \fn template template QVector::QVector(InputIterator first, InputIterator last) - \since 5.14 - - Constructs a vector with the contents in the iterator range [\a first, \a last). - - The value type of \c InputIterator must be convertible to \c T. -*/ - -/*! - \fn template QVector::QVector(QArrayDataPointerRef ref) - \internal -*/ - -/*! \fn template QVector::~QVector() - - Destroys the vector. -*/ - -/*! \fn template QVector &QVector::operator=(const QVector &other) - - Assigns \a other to this vector and returns a reference to this - vector. -*/ - -/*! - \fn template QVector &QVector::operator=(QVector &&other) - - Move-assigns \a other to this QVector instance. - - \since 5.2 -*/ - -/*! - \fn template QVector &QVector::operator=(std::initializer_list args) - - Assigns the collection of values in \a args to this QVector instance. - - This operator is only enabled if the compiler supports C++11 initializer - lists. - - \since 5.14 -*/ - -/*! \fn template void QVector::swap(QVector &other) - \since 4.8 - - Swaps vector \a other with this vector. This operation is very fast and - never fails. -*/ - -/*! \fn template void QVector::swapItemsAt(int i, int j) - \since 5.14 - - Exchange the item at index position \a i with the item at index - position \a j. This function assumes that both \a i and \a j are - at least 0 but less than size(). To avoid failure, test that both - \a i and \a j are at least 0 and less than size(). -*/ - - -/*! \fn template bool QVector::operator==(const QVector &other) const - - Returns \c true if \a other is equal to this vector; otherwise - returns \c false. - - Two vectors are considered equal if they contain the same values - in the same order. - - This function requires the value type to have an implementation - of \c operator==(). - - \sa operator!=() -*/ - -/*! \fn template bool QVector::operator!=(const QVector &other) const - - Returns \c true if \a other is not equal to this vector; otherwise - returns \c false. - - Two vectors are considered equal if they contain the same values - in the same order. - - This function requires the value type to have an implementation - of \c operator==(). - - \sa operator==() -*/ - -/*! \fn template bool operator<(const QVector &lhs, const QVector &rhs) - \since 5.6 - \relates QVector - - Returns \c true if vector \a lhs is - \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} - {lexicographically less than} \a rhs; otherwise returns \c false. - - This function requires the value type to have an implementation - of \c operator<(). -*/ - -/*! \fn template bool operator<=(const QVector &lhs, const QVector &rhs) - \since 5.6 - \relates QVector - - Returns \c true if vector \a lhs is - \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} - {lexicographically less than or equal to} \a rhs; otherwise returns \c false. - - This function requires the value type to have an implementation - of \c operator<(). -*/ - -/*! \fn template bool operator>(const QVector &lhs, const QVector &rhs) - \since 5.6 - \relates QVector - - Returns \c true if vector \a lhs is - \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} - {lexicographically greater than} \a rhs; otherwise returns \c false. - - This function requires the value type to have an implementation - of \c operator<(). -*/ - -/*! \fn template bool operator>=(const QVector &lhs, const QVector &rhs) - \since 5.6 - \relates QVector - - Returns \c true if vector \a lhs is - \l{http://en.cppreference.com/w/cpp/algorithm/lexicographical_compare} - {lexicographically greater than or equal to} \a rhs; otherwise returns \c false. - - This function requires the value type to have an implementation - of \c operator<(). -*/ - -/*! - \fn template size_t qHash(const QVector &key, size_t seed = 0) - \since 5.6 - \relates QVector - - Returns the hash value for \a key, - using \a seed to seed the calculation. - - This function requires qHash() to be overloaded for the value type \c T. -*/ - -/*! \fn template int QVector::size() const - - Returns the number of items in the vector. - - \sa isEmpty(), resize() -*/ - -/*! \fn template bool QVector::isEmpty() const - - Returns \c true if the vector has size 0; otherwise returns \c false. - - \sa size(), resize() -*/ - -/*! \fn template void QVector::resize(int size) - - Sets the size of the vector to \a size. If \a size is greater than the - current size, elements are added to the end; the new elements are - initialized with a \l{default-constructed value}. If \a size is less - than the current size, elements are removed from the end. - - Since Qt 5.6, resize() doesn't shrink the capacity anymore. - To shed excess capacity, use squeeze(). - - \sa size() -*/ - -/*! \fn template int QVector::capacity() const - - Returns the maximum number of items that can be stored in the - vector without forcing a reallocation. - - The sole purpose of this function is to provide a means of fine - tuning QVector's memory usage. In general, you will rarely ever - need to call this function. If you want to know how many items are - in the vector, call size(). - - \note a statically allocated vector will report a capacity of 0, - even if it's not empty. - - \sa reserve(), squeeze() -*/ - -/*! \fn template void QVector::reserve(int size) - - Attempts to allocate memory for at least \a size elements. If you - know in advance how large the vector will be, you should call this - function to prevent reallocations and memory fragmentation. - - If \a size is an underestimate, the worst that will happen is that - the QVector will be a bit slower. If \a size is an overestimate, you - may have used more memory than the normal QVector growth strategy - would have allocated—or you may have used less. - - An alternative to reserve() is calling resize(). Whether or not that is - faster than reserve() depends on the element type, because resize() - default-constructs all elements, and requires assignment to existing - entries rather than calling append(), which copy- or move-constructs. - For simple types, like \c int or \c double, resize() is typically faster, - but for anything more complex, you should prefer reserve(). - - \warning If the size passed to resize() was underestimated, you run out - of allocated space and into undefined behavior. This problem does not - exist with reserve(), because it treats the size as just a hint. - - \sa squeeze(), capacity() -*/ - -/*! \fn template void QVector::squeeze() - - Releases any memory not required to store the items. - - The sole purpose of this function is to provide a means of fine - tuning QVector's memory usage. In general, you will rarely ever - need to call this function. - - \sa reserve(), capacity() -*/ - -/*! \fn template void QVector::detach() - - \internal -*/ - -/*! \fn template bool QVector::isDetached() const - - \internal -*/ - -/*! \fn template void QVector::setSharable(bool sharable) - - \internal -*/ - -/*! \fn template bool QVector::isSharedWith(const QVector &other) const - - \internal -*/ - -/*! \fn template T *QVector::data() - - Returns a pointer to the data stored in the vector. The pointer - can be used to access and modify the items in the vector. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 6 - - The pointer remains valid as long as the vector isn't - reallocated. - - This function is mostly useful to pass a vector to a function - that accepts a plain C++ array. - - \sa constData(), operator[]() -*/ - -/*! \fn template const T *QVector::data() const - - \overload -*/ - -/*! \fn template const T *QVector::constData() const - - Returns a const pointer to the data stored in the vector. The - pointer can be used to access the items in the vector. - The pointer remains valid as long as the vector isn't - reallocated. - - This function is mostly useful to pass a vector to a function - that accepts a plain C++ array. - - \sa data(), operator[]() -*/ - -/*! \fn template void QVector::clear() - - Removes all the elements from the vector. - - \note Until Qt 5.6, this also released the memory used by - the vector. From Qt 5.7, the capacity is preserved. To shed - all capacity, swap with a default-constructed vector: - \code - QVector v ...; - QVector().swap(v); - Q_ASSERT(v.capacity() == 0); - \endcode - or call squeeze(). - - \sa squeeze() -*/ - -/*! \fn template const T &QVector::at(int i) const - - Returns the item at index position \a i in the vector. - - \a i must be a valid index position in the vector (i.e., 0 <= \a - i < size()). - - \sa value(), operator[]() -*/ - -/*! \fn template T &QVector::operator[](int i) - - Returns the item at index position \a i as a modifiable reference. - - \a i must be a valid index position in the vector (i.e., 0 <= \a i - < size()). - - Note that using non-const operators can cause QVector to do a deep - copy. - - \sa at(), value() -*/ - -/*! \fn template const T &QVector::operator[](int i) const - - \overload - - Same as at(\a i). -*/ - -/*! - \fn template void QVector::append(const T &value) - - Inserts \a value at the end of the vector. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 7 - - This is the same as calling resize(size() + 1) and assigning \a - value to the new last element in the vector. - - This operation is relatively fast, because QVector typically - allocates more memory than necessary, so it can grow without - reallocating the entire vector each time. - - \sa operator<<(), prepend(), insert() -*/ - -/*! - \fn template void QVector::append(T &&value) - \since 5.6 - - \overload - - Example: - \snippet code/src_corelib_tools_qvector.cpp move-append -*/ - -/*! \fn template void QVector::append(const QVector &value) - - \overload - - \since 5.5 - - Appends the items of the \a value vector to this vector. - - \sa operator<<(), operator+=() -*/ - - -/*! - \fn template void QVector::prepend(const T &value) - \fn template void QVector::prepend(T &&value) - - Inserts \a value at the beginning of the vector. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 8 - - This is the same as vector.insert(0, \a value). - - For large vectors, this operation can be slow (\l{linear time}), - because it requires moving all the items in the vector by one - position further in memory. If you want a container class that - provides a fast prepend operation, use std::list - instead. - - \sa append(), insert() -*/ - -/*! - \fn template template T &QVector::emplaceBack(Args&&... args) - \fn template template T &QVector::emplace_back(Args&&... args) - - Adds a new element to the end for the container. This new element - is constructed in-place using \a args as the arguments for its - construction. - - Returns a reference to the new element. - - Example: - \snippet code/src_corelib_tools_qvector.cpp emplace-back - - It is also possible to access a newly created object by using - returned reference: - \snippet code/src_corelib_tools_qvector.cpp emplace-back-ref - - This is the same as vector.emplace(vector.size(), \a args). - - \sa emplace -*/ - -/*! \fn template void QVector::insert(int i, const T &value) - \fn template void QVector::insert(int i, T &&value) - - Inserts \a value at index position \a i in the vector. If \a i is - 0, the value is prepended to the vector. If \a i is size(), the - value is appended to the vector. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 9 - - For large vectors, this operation can be slow (\l{linear time}), - because it requires moving all the items at indexes \a i and - above by one position further in memory. If you want a container - class that provides a fast insert() function, use std::list - instead. - - \sa append(), prepend(), remove() -*/ - -/*! \fn template void QVector::insert(int i, int count, const T &value) - - \overload - - Inserts \a count copies of \a value at index position \a i in the - vector. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 10 -*/ - -/*! - \fn template QVector::iterator QVector::insert(iterator before, const T &value) - \fn template QVector::iterator QVector::insert(iterator before, T &&value) - - \overload - - Inserts \a value in front of the item pointed to by the iterator - \a before. Returns an iterator pointing at the inserted item. -*/ - -/*! \fn template QVector::iterator QVector::insert(iterator before, int count, const T &value) - - Inserts \a count copies of \a value in front of the item pointed to - by the iterator \a before. Returns an iterator pointing at the - first of the inserted items. -*/ - -/*! - \fn template template QVector::iterator QVector::emplace(int i, Args&&... args) - - Extends the container by inserting a new element at position \a i. - This new element is constructed in-place using \a args as the - arguments for its construction. - - Returns an iterator to the new element. - - Example: - \snippet code/src_corelib_tools_qvector.cpp emplace - - \note It is garanteed that the element will be created in place - at the beginning, but after that it might be copied or - moved to the right position. - - \sa emplaceBack -*/ - - -/*! \fn template void QVector::replace(int i, const T &value) - - Replaces the item at index position \a i with \a value. - - \a i must be a valid index position in the vector (i.e., 0 <= \a - i < size()). - - \sa operator[](), remove() -*/ - -/*! \fn template void QVector::remove(int i) - - \overload - - Removes the element at index position \a i. - - \sa insert(), replace(), fill() -*/ - -/*! \fn template void QVector::remove(int i, int count) - - \overload - - Removes \a count elements from the middle of the vector, starting at - index position \a i. - - \sa insert(), replace(), fill() -*/ - -/*! \fn template void QVector::removeAt(int i) - \since 5.2 - - Removes the element at index position \a i. - Equivalent to - \code - remove(i); - \endcode - - Provided for compatibility with QList. - - \sa remove(), QList::removeAt() -*/ - -/*! \fn template int QVector::removeAll(const T &t) - \since 5.4 - - Removes all elements that compare equal to \a t from the - vector. Returns the number of elements removed, if any. - - Provided for compatibility with QList. - - \sa removeOne(), QList::removeAll() -*/ - -/*! \fn template bool QVector::removeOne(const T &t) - \since 5.4 - - Removes the first element that compares equal to \a t from the - vector. Returns whether an element was, in fact, removed. - - Provided for compatibility with QList. - - \sa removeAll(), QList::removeOne() -*/ - -/*! \fn template int QVector::length() const - \since 5.2 - - Same as size() and count(). - - Provided for compatibility with QList. - - \sa size(), count(), QList::length() -*/ - -/*! \fn template T QVector::takeAt(int i) - \since 5.2 - - Removes the element at index position \a i and returns it. - - Equivalent to - \code - T t = at(i); - remove(i); - return t; - \endcode - - Provided for compatibility with QList. - - \sa takeFirst(), takeLast(), QList::takeAt() -*/ - -/*! \fn template void QVector::move(int from, int to) - \since 5.6 - - Moves the item at index position \a from to index position \a to. - - Provided for compatibility with QList. - - \sa QList::move() -*/ - -/*! \fn template void QVector::removeFirst() - \since 5.1 - Removes the first item in the vector. Calling this function is - equivalent to calling remove(0). The vector must not be empty. If - the vector can be empty, call isEmpty() before calling this - function. - - \sa remove(), takeFirst(), isEmpty() -*/ - -/*! \fn template void QVector::removeLast() - \since 5.1 - Removes the last item in the vector. Calling this function is - equivalent to calling remove(size() - 1). The vector must not be - empty. If the vector can be empty, call isEmpty() before calling - this function. - - \sa remove(), takeLast(), removeFirst(), isEmpty() -*/ - -/*! \fn template T QVector::takeFirst() - \since 5.1 - - Removes the first item in the vector and returns it. This function - assumes the vector is not empty. To avoid failure, call isEmpty() - before calling this function. - - \sa takeLast(), removeFirst() -*/ - -/*! \fn template T QVector::takeLast() - \since 5.1 - - Removes the last item in the list and returns it. This function - assumes the vector is not empty. To avoid failure, call isEmpty() - before calling this function. - - If you don't use the return value, removeLast() is more - efficient. - - \sa takeFirst(), removeLast() -*/ - -/*! - \fn template template QVector::iterator QVector::emplace(QVector::iterator before, Args&&... args) - - \overload - - Creates a new element in front of the item pointed to by the - iterator \a before. This new element is constructed in-place - using \a args as the arguments for its construction. - - Returns an iterator to the new element. -*/ - -/*! \fn template QVector &QVector::fill(const T &value, int size = -1) - - Assigns \a value to all items in the vector. If \a size is - different from -1 (the default), the vector is resized to size \a - size beforehand. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 11 - - \sa resize() -*/ - -/*! \fn template int QVector::indexOf(const T &value, int from = 0) const - - Returns the index position of the first occurrence of \a value in - the vector, searching forward from index position \a from. - Returns -1 if no item matched. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 12 - - This function requires the value type to have an implementation of - \c operator==(). - - \sa lastIndexOf(), contains() -*/ - -/*! \fn template int QVector::lastIndexOf(const T &value, int from = -1) const - - Returns the index position of the last occurrence of the value \a - value in the vector, searching backward from index position \a - from. If \a from is -1 (the default), the search starts at the - last item. Returns -1 if no item matched. - - Example: - \snippet code/src_corelib_tools_qvector.cpp 13 - - This function requires the value type to have an implementation of - \c operator==(). - - \sa indexOf() -*/ - -/*! \fn template bool QVector::contains(const T &value) const - - Returns \c true if the vector contains an occurrence of \a value; - otherwise returns \c false. - - This function requires the value type to have an implementation of - \c operator==(). - - \sa indexOf(), count() -*/ - -/*! \fn template bool QVector::startsWith(const T &value) const - \since 4.5 - - Returns \c true if this vector is not empty and its first - item is equal to \a value; otherwise returns \c false. - - \sa isEmpty(), first() -*/ - -/*! \fn template bool QVector::endsWith(const T &value) const - \since 4.5 - - Returns \c true if this vector is not empty and its last - item is equal to \a value; otherwise returns \c false. - - \sa isEmpty(), last() -*/ - - -/*! \fn template int QVector::count(const T &value) const - - Returns the number of occurrences of \a value in the vector. - - This function requires the value type to have an implementation of - \c operator==(). - - \sa contains(), indexOf() -*/ - -/*! \fn template int QVector::count() const - - \overload - - Same as size(). -*/ - -/*! \fn template QVector::iterator QVector::begin() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in - the vector. - - \sa constBegin(), end() -*/ - -/*! \fn template QVector::const_iterator QVector::begin() const - - \overload -*/ - -/*! \fn template QVector::const_iterator QVector::cbegin() const - \since 5.0 - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item - in the vector. - - \sa begin(), cend() -*/ - -/*! \fn template QVector::const_iterator QVector::constBegin() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item - in the vector. - - \sa begin(), constEnd() -*/ - -/*! \fn template QVector::iterator QVector::end() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item - after the last item in the vector. - - \sa begin(), constEnd() -*/ - -/*! \fn template QVector::const_iterator QVector::end() const - - \overload -*/ - -/*! \fn template QVector::const_iterator QVector::cend() const - \since 5.0 - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary - item after the last item in the vector. - - \sa cbegin(), end() -*/ - -/*! \fn template QVector::const_iterator QVector::constEnd() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary - item after the last item in the vector. - - \sa constBegin(), end() -*/ - -/*! \fn template QVector::reverse_iterator QVector::rbegin() - \since 5.6 - - Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first - item in the vector, in reverse order. - - \sa begin(), crbegin(), rend() -*/ - -/*! \fn template QVector::const_reverse_iterator QVector::rbegin() const - \since 5.6 - \overload -*/ - -/*! \fn template QVector::const_reverse_iterator QVector::crbegin() const - \since 5.6 - - Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first - item in the vector, in reverse order. - - \sa begin(), rbegin(), rend() -*/ - -/*! \fn template QVector::reverse_iterator QVector::rend() - \since 5.6 - - Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past - the last item in the vector, in reverse order. - - \sa end(), crend(), rbegin() -*/ - -/*! \fn template QVector::const_reverse_iterator QVector::rend() const - \since 5.6 - \overload -*/ - -/*! \fn template QVector::const_reverse_iterator QVector::crend() const - \since 5.6 - - Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one - past the last item in the vector, in reverse order. - - \sa end(), rend(), rbegin() -*/ - -/*! \fn template QVector::iterator QVector::erase(iterator pos) - - Removes the item pointed to by the iterator \a pos from the - vector, and returns an iterator to the next item in the vector - (which may be end()). - - \sa insert(), remove() -*/ - -/*! \fn template QVector::iterator QVector::erase(iterator begin, iterator end) - - \overload - - Removes all the items from \a begin up to (but not including) \a - end. Returns an iterator to the same item that \a end referred to - before the call. -*/ - -/*! \fn template T& QVector::first() - - Returns a reference to the first item in the vector. This - function assumes that the vector isn't empty. - - \sa last(), isEmpty(), constFirst() -*/ - -/*! \fn template const T& QVector::first() const - - \overload -*/ - -/*! \fn template const T& QVector::constFirst() const - \since 5.6 - - Returns a const reference to the first item in the vector. This - function assumes that the vector isn't empty. - - \sa constLast(), isEmpty(), first() -*/ - -/*! \fn template T& QVector::last() - - Returns a reference to the last item in the vector. This function - assumes that the vector isn't empty. - - \sa first(), isEmpty(), constLast() -*/ - -/*! \fn template const T& QVector::last() const - - \overload -*/ - -/*! \fn template const T& QVector::constLast() const - \since 5.6 - - Returns a const reference to the last item in the vector. This function - assumes that the vector isn't empty. - - \sa constFirst(), isEmpty(), last() -*/ - -/*! \fn template T QVector::value(int i) const - - Returns the value at index position \a i in the vector. - - If the index \a i is out of bounds, the function returns - a \l{default-constructed value}. If you are certain that - \a i is within bounds, you can use at() instead, which is slightly - faster. - - \sa at(), operator[]() -*/ - -/*! \fn template T QVector::value(int i, const T &defaultValue) const - - \overload - - If the index \a i is out of bounds, the function returns - \a defaultValue. -*/ - -/*! \fn template void QVector::push_back(const T &value) - - This function is provided for STL compatibility. It is equivalent - to append(\a value). -*/ - -/*! \fn template void QVector::push_back(T &&value) - \since 5.6 - \overload -*/ - -/*! - \fn template void QVector::push_front(const T &value) - \fn template void QVector::push_front(T &&value) - - This function is provided for STL compatibility. It is equivalent - to prepend(\a value). -*/ - -/*! \fn template void QVector::pop_front() - - This function is provided for STL compatibility. It is equivalent - to removeFirst(). -*/ - -/*! \fn template void QVector::pop_back() - - This function is provided for STL compatibility. It is equivalent - to removeLast(). -*/ - -/*! \fn template T& QVector::front() - - This function is provided for STL compatibility. It is equivalent - to first(). -*/ - -/*! \fn template QVector::const_reference QVector::front() const - - \overload -*/ - -/*! \fn template QVector::reference QVector::back() - - This function is provided for STL compatibility. It is equivalent - to last(). -*/ - -/*! \fn template QVector::const_reference QVector::back() const - - \overload -*/ - -/*! \fn template void QVector::shrink_to_fit() - \since 5.10 - - This function is provided for STL compatibility. It is equivalent - to squeeze(). -*/ - -/*! \fn template bool QVector::empty() const - - This function is provided for STL compatibility. It is equivalent - to isEmpty(), returning \c true if the vector is empty; otherwise - returns \c false. -*/ - -/*! \fn template QVector &QVector::operator+=(const QVector &other) - - Appends the items of the \a other vector to this vector and - returns a reference to this vector. - - \sa operator+(), append() -*/ - -/*! \fn template void QVector::operator+=(const T &value) - - \overload - - Appends \a value to the vector. - - \sa append(), operator<<() -*/ - -/*! \fn template void QVector::operator+=(T &&value) - \since 5.11 - - \overload - - \sa append(), operator<<() -*/ - -/*! \fn template QVector QVector::operator+(const QVector &other) const - - Returns a vector that contains all the items in this vector - followed by all the items in the \a other vector. - - \sa operator+=() -*/ - -/*! \fn template QVector &QVector::operator<<(const T &value) - - Appends \a value to the vector and returns a reference to this - vector. - - \sa append(), operator+=() -*/ - -/*! \fn template QVector &QVector::operator<<(T &&value) - \since 5.11 - - \overload - - \sa append(), operator+=() -*/ - - -/*! \fn template QVector &QVector::operator<<(const QVector &other) - - Appends \a other to the vector and returns a reference to the - vector. -*/ - -/*! \typedef QVector::iterator - - The QVector::iterator typedef provides an STL-style non-const - iterator for QVector and QStack. - - QVector provides both \l{STL-style iterators} and \l{Java-style - iterators}. The STL-style non-const iterator is simply a typedef - for "T *" (pointer to T). - - \warning Iterators on implicitly shared containers do not work - exactly like STL-iterators. You should avoid copying a container - while iterators are active on that container. For more information, - read \l{Implicit sharing iterator problem}. - - \sa QVector::begin(), QVector::end(), QVector::const_iterator, QMutableVectorIterator -*/ - -/*! \typedef QVector::const_iterator - - The QVector::const_iterator typedef provides an STL-style const - iterator for QVector and QStack. - - QVector provides both \l{STL-style iterators} and \l{Java-style - iterators}. The STL-style const iterator is simply a typedef for - "const T *" (pointer to const T). - - \warning Iterators on implicitly shared containers do not work - exactly like STL-iterators. You should avoid copying a container - while iterators are active on that container. For more information, - read \l{Implicit sharing iterator problem}. - - \sa QVector::constBegin(), QVector::constEnd(), QVector::iterator, QVectorIterator -*/ - -/*! \typedef QVector::reverse_iterator - \since 5.6 - - The QVector::reverse_iterator typedef provides an STL-style non-const - reverse iterator for QVector. - - It is simply a typedef for \c{std::reverse_iterator}. - - \warning Iterators on implicitly shared containers do not work - exactly like STL-iterators. You should avoid copying a container - while iterators are active on that container. For more information, - read \l{Implicit sharing iterator problem}. - - \sa QVector::rbegin(), QVector::rend(), QVector::const_reverse_iterator, QVector::iterator -*/ - -/*! \typedef QVector::const_reverse_iterator - \since 5.6 - - The QVector::const_reverse_iterator typedef provides an STL-style const - reverse iterator for QVector. - - It is simply a typedef for \c{std::reverse_iterator}. - - \warning Iterators on implicitly shared containers do not work - exactly like STL-iterators. You should avoid copying a container - while iterators are active on that container. For more information, - read \l{Implicit sharing iterator problem}. - - \sa QVector::rbegin(), QVector::rend(), QVector::reverse_iterator, QVector::const_iterator -*/ - -/*! \typedef QVector::Iterator - - Qt-style synonym for QVector::iterator. -*/ - -/*! \typedef QVector::ConstIterator - - Qt-style synonym for QVector::const_iterator. -*/ - -/*! \typedef QVector::const_pointer - - Typedef for const T *. Provided for STL compatibility. -*/ - -/*! \typedef QVector::const_reference - - Typedef for T &. Provided for STL compatibility. -*/ - -/*! \typedef QVector::difference_type - - Typedef for ptrdiff_t. Provided for STL compatibility. -*/ - -/*! \typedef QVector::pointer - - Typedef for T *. Provided for STL compatibility. -*/ - -/*! \typedef QVector::reference - - Typedef for T &. Provided for STL compatibility. -*/ - -/*! \typedef QVector::size_type - - Typedef for int. Provided for STL compatibility. -*/ - -/*! \typedef QVector::value_type - - Typedef for T. Provided for STL compatibility. -*/ - -/*! \fn template QList QVector::toList() const - - Returns a QList object with the data contained in this QVector. - - Example: - - \snippet code/src_corelib_tools_qvector.cpp 14 - - \include containers-range-constructor.qdocinc - - \sa fromList(), QList::fromVector() -*/ - -/*! \fn template QVector QVector::fromList(const QList &list) - - Returns a QVector object with the data contained in \a list. - - Example: - - \snippet code/src_corelib_tools_qvector.cpp 15 - - \include containers-range-constructor.qdocinc - - \sa toList(), QList::toVector() -*/ - -/*! \fn template QVector QVector::fromStdVector(const std::vector &vector) - - Returns a QVector object with the data contained in \a vector. The - order of the elements in the QVector is the same as in \a vector. - - Example: - - \snippet code/src_corelib_tools_qvector.cpp 16 - - \include containers-range-constructor.qdocinc - - \sa toStdVector(), QList::fromStdList() -*/ - -/*! \fn template std::vector QVector::toStdVector() const - - Returns a std::vector object with the data contained in this QVector. - Example: - - \snippet code/src_corelib_tools_qvector.cpp 17 - - \include containers-range-constructor.qdocinc - - \sa fromStdVector(), QList::toStdList() -*/ - -/*! \fn template QDataStream &operator<<(QDataStream &out, const QVector &vector) - \relates QVector - - Writes the vector \a vector to stream \a out. - - This function requires the value type to implement \c operator<<(). - - \sa{Serializing Qt Data Types}{Format of the QDataStream operators} -*/ - -/*! \fn template QDataStream &operator>>(QDataStream &in, QVector &vector) - \relates QVector - - Reads a vector from stream \a in into \a vector. - - This function requires the value type to implement \c operator>>(). - - \sa{Serializing Qt Data Types}{Format of the QDataStream operators} -*/ diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 27849a2589..f5d034e1e7 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -49,6 +49,7 @@ #include #include #include +#include #if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage); @@ -63,7 +64,6 @@ class QIODevice; class QStringList; class QTransform; class QVariant; -template class QVector; struct QImageData; diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index b4d79462d4..49174e7510 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -44,6 +44,7 @@ #include #include #include +#include #ifndef QT_NO_DATASTREAM #include @@ -52,7 +53,6 @@ QT_BEGIN_NAMESPACE -template class QVector; class QVariant; struct QRegionPrivate; diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index 175a34313c..2b4cf5df6f 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -47,6 +47,7 @@ #include #include #include +#include Q_MOC_INCLUDE() QT_BEGIN_NAMESPACE @@ -68,7 +69,6 @@ class QRectF; class QTextOption; class QTextCursor; -template class QVector; namespace Qt { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index dab69a8b89..4d8112c679 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -347,12 +347,12 @@ struct QScriptItem int glyph_data_offset; Q_DECL_CONSTEXPR QFixed height() const noexcept { return ascent + descent; } private: - friend class QVector; - QScriptItem() {} // for QVector, don't use + friend class QList; + QScriptItem() {} // for QList, don't use }; Q_DECLARE_TYPEINFO(QScriptItem, Q_PRIMITIVE_TYPE); -typedef QVector QScriptItemArray; +typedef QList QScriptItemArray; struct Q_AUTOTEST_EXPORT QScriptLine { diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h index 8ebf7294dd..7253b2835e 100644 --- a/src/network/access/qhsts_p.h +++ b/src/network/access/qhsts_p.h @@ -61,13 +61,12 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE -template class QVector; - class Q_AUTOTEST_EXPORT QHstsCache { public: diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h index fe1da23409..93cadc5bc6 100644 --- a/src/network/ssl/qdtls.h +++ b/src/network/ssl/qdtls.h @@ -47,6 +47,7 @@ #include #include +#include Q_MOC_INCLUDE() @@ -109,7 +110,6 @@ private: }; class QSslPreSharedKeyAuthenticator; -template class QVector; class QSslConfiguration; class QSslCipher; class QSslError; diff --git a/src/plugins/generic/tuiotouch/qoscbundle_p.h b/src/plugins/generic/tuiotouch/qoscbundle_p.h index cb3ec4d251..5aee310017 100644 --- a/src/plugins/generic/tuiotouch/qoscbundle_p.h +++ b/src/plugins/generic/tuiotouch/qoscbundle_p.h @@ -43,7 +43,7 @@ #include "qoscmessage_p.h" -#include +#include QT_BEGIN_NAMESPACE @@ -51,22 +51,22 @@ class QByteArray; class QOscBundle { - QOscBundle(); // for QVector, don't use - friend class QVector; + QOscBundle(); // for QList, don't use + friend class QList; public: explicit QOscBundle(const QByteArray &data); bool isValid() const { return m_isValid; } - QVector bundles() const { return m_bundles; } - QVector messages() const { return m_messages; } + QList bundles() const { return m_bundles; } + QList messages() const { return m_messages; } private: bool m_isValid; bool m_immediate; quint32 m_timeEpoch; quint32 m_timePico; - QVector m_bundles; - QVector m_messages; + QList m_bundles; + QList m_messages; }; Q_DECLARE_TYPEINFO(QOscBundle, Q_MOVABLE_TYPE); diff --git a/src/plugins/generic/tuiotouch/qoscmessage_p.h b/src/plugins/generic/tuiotouch/qoscmessage_p.h index 76d40ceb18..46c6ca3918 100644 --- a/src/plugins/generic/tuiotouch/qoscmessage_p.h +++ b/src/plugins/generic/tuiotouch/qoscmessage_p.h @@ -43,7 +43,6 @@ #include #include -#include #include @@ -51,8 +50,8 @@ QT_BEGIN_NAMESPACE class QOscMessage { - QOscMessage(); // for QVector, don't use - friend class QVector; + QOscMessage(); // for QList, don't use + friend class QList; public: explicit QOscMessage(const QByteArray &data); diff --git a/src/sql/kernel/qsqlcachedresult_p.h b/src/sql/kernel/qsqlcachedresult_p.h index 1bca1fd090..0b9dfd3e9a 100644 --- a/src/sql/kernel/qsqlcachedresult_p.h +++ b/src/sql/kernel/qsqlcachedresult_p.h @@ -54,11 +54,11 @@ #include #include "QtSql/qsqlresult.h" #include "QtSql/private/qsqlresult_p.h" +#include QT_BEGIN_NAMESPACE class QVariant; -template class QVector; class QSqlCachedResultPrivate; diff --git a/src/sql/kernel/qsqlresult.h b/src/sql/kernel/qsqlresult.h index 43d53d4027..a7fdae834a 100644 --- a/src/sql/kernel/qsqlresult.h +++ b/src/sql/kernel/qsqlresult.h @@ -42,6 +42,7 @@ #include #include +#include // for testing: class tst_QSqlQuery; @@ -51,7 +52,7 @@ QT_BEGIN_NAMESPACE class QString; class QSqlRecord; -template class QVector; +class QVariant; class QSqlDriver; class QSqlError; class QSqlResultPrivate; diff --git a/src/widgets/kernel/qlayoutengine_p.h b/src/widgets/kernel/qlayoutengine_p.h index 2999bae646..9d221cb34e 100644 --- a/src/widgets/kernel/qlayoutengine_p.h +++ b/src/widgets/kernel/qlayoutengine_p.h @@ -54,11 +54,10 @@ #include #include "QtWidgets/qlayoutitem.h" #include "QtWidgets/qstyle.h" +#include QT_BEGIN_NAMESPACE -template class QVector; - struct QLayoutStruct { inline void init(int stretchFactor = 0, int minSize = 0) { diff --git a/sync.profile b/sync.profile index 4eb9b0433e..c9359dde57 100644 --- a/sync.profile +++ b/sync.profile @@ -40,7 +40,7 @@ "qconfig.h" => "QtConfig", "qplugin.h" => "QtPlugin", "qalgorithms.h" => "QtAlgorithms", - "qlist.h" => "QList", + "qvector.h" => "QVector", "qcontainerfwd.h" => "QtContainerFwd", "qdebug.h" => "QtDebug", "qevent.h" => "QtEvents", diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 0091636172..a8f6914115 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -1320,13 +1320,13 @@ void tst_QMetaObject::normalizedSignature_data() QTest::newRow("function ptr spaces") << "void foo( void ( * ) ( void ))" << "void foo(void(*)())"; QTest::newRow("function ptr void*") << "void foo(void(*)(void*))" << "void foo(void(*)(void*))"; QTest::newRow("function ptr void* spaces") << "void foo( void ( * ) ( void * ))" << "void foo(void(*)(void*))"; - QTest::newRow("template args") << " void foo( QMap, QVector) " - << "void foo(QMap,QVector)"; + QTest::newRow("template args") << " void foo( QMap, QList) " + << "void foo(QMap,QList)"; QTest::newRow("void template args") << " void foo( Foo, Bar ) " << "void foo(Foo,Bar)"; QTest::newRow("void* template args") << " void foo( Foo, Bar ) " << "void foo(Foo,Bar)"; - QTest::newRow("rettype") << "QVector foo()" << "QVectorfoo()"; + QTest::newRow("rettype") << "QList foo()" << "QListfoo()"; QTest::newRow("rettype void template") << "Foo foo()" << "Foofoo()"; QTest::newRow("const rettype") << "const QString *foo()" << "const QString*foo()"; QTest::newRow("const ref") << "const QString &foo()" << "const QString&foo()"; @@ -1337,18 +1337,18 @@ void tst_QMetaObject::normalizedSignature_data() QTest::newRow("const4") << "void foo(const int)" << "void foo(int)"; QTest::newRow("const5") << "void foo(const int, int const, const int &, int const &)" << "void foo(int,int,int,int)"; - QTest::newRow("const6") << "void foo(QVector)" << "void foo(QVector)"; - QTest::newRow("const7") << "void foo(QVector)" << "void foo(QVector)"; - QTest::newRow("const8") << "void foo(QVector)" << "void foo(QVector)"; + QTest::newRow("const6") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const7") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const8") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const9") << "void foo(const Foo)" << "void foo(Foo)"; QTest::newRow("const10") << "void foo(Fooconst)" << "void foo(Foo)"; QTest::newRow("const11") << "void foo(Foo *const)" << "void foo(Foo*)"; QTest::newRow("const12") << "void foo(Fooconst*const *const)" << "void foo(const Foo*const*)"; QTest::newRow("const13") << "void foo(const Foo&)" << "void foo(Foo)"; QTest::newRow("const14") << "void foo(Fooconst&)" << "void foo(Foo)"; - QTest::newRow("QList") << "void foo(QList)" << "void foo(QVector)"; - QTest::newRow("QList1") << "void foo(const Template)" - << "void foo(Template)"; + QTest::newRow("QVector") << "void foo(QVector)" << "void foo(QList)"; + QTest::newRow("QVector1") << "void foo(const Template)" + << "void foo(Template)"; QTest::newRow("refref") << "const char* foo(const X &&,X const &&, const X* &&) && " << "const char*foo(const X&&,const X&&,const X*&&)&&"; @@ -1373,13 +1373,13 @@ void tst_QMetaObject::normalizedType_data() QTest::newRow("white") << " int " << "int"; QTest::newRow("const1") << "int const *" << "const int*"; QTest::newRow("const2") << "const int *" << "const int*"; - QTest::newRow("template1") << "QVector" << "QVector"; - QTest::newRow("template2") << "QVector" << "QVector"; + QTest::newRow("template1") << "QList" << "QList"; + QTest::newRow("template2") << "QList" << "QList"; QTest::newRow("template3") << "QMap" << "QMap"; QTest::newRow("template4") << "const QMap &" << "QMap"; - QTest::newRow("template5") << "QVector< ::Foo::Bar>" << "QVector<::Foo::Bar>"; - QTest::newRow("template6") << "QVector<::Foo::Bar>" << "QVector<::Foo::Bar>"; - QTest::newRow("template7") << "QVector >" << "QVector>"; + QTest::newRow("template5") << "QList< ::Foo::Bar>" << "QList<::Foo::Bar>"; + QTest::newRow("template6") << "QList<::Foo::Bar>" << "QList<::Foo::Bar>"; + QTest::newRow("template7") << "QList >" << "QList>"; QTest::newRow("template8") << "QMap" << "QMap"; QTest::newRow("template9") << "QPair , QPair > >" #ifdef _LIBCPP_VERSION @@ -1387,7 +1387,7 @@ void tst_QMetaObject::normalizedType_data() #else << "std::pair,std::pair>>"; #endif - QTest::newRow("template10") << "QList const" << "QVector"; + QTest::newRow("template10") << "QVector const" << "QList"; QTest::newRow("template11") << " QSharedPointer> 2 )> > const & " << "QSharedPointer>2)>>"; QTest::newRow("template_sub") << "X<( Y < 8), (Y >6)> const & " << "X<(Y<8),(Y>6)>"; @@ -1402,7 +1402,8 @@ void tst_QMetaObject::normalizedType_data() QTest::newRow("struct2") << "struct foo const*" << "const foo*"; QTest::newRow("enum") << "enum foo" << "foo"; QTest::newRow("void") << "void" << "void"; - QTest::newRow("QList") << "QList" << "QVector"; + QTest::newRow("QList") << "QList" << "QList"; + QTest::newRow("QVector") << "QVector" << "QList"; QTest::newRow("refref") << "X const*const&&" << "const X*const&&"; QTest::newRow("refref2") << "const X&&" << "const X&&"; QTest::newRow("long1") << "long unsigned int long" << "unsigned long long"; diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 651efa53cf..48b46dd98f 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -583,11 +583,11 @@ void tst_QMetaType::typeName_data() // automatic registration QTest::newRow("QHash") << ::qMetaTypeId >() << QString::fromLatin1("QHash"); QTest::newRow("QMap") << ::qMetaTypeId >() << QString::fromLatin1("QMap"); - QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QVector>"); + QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QList>"); // automatic registration with automatic QList to QVector aliasing - QTest::newRow("QList") << ::qMetaTypeId >() << QString::fromLatin1("QVector"); - QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QVector>"); + QTest::newRow("QList") << ::qMetaTypeId >() << QString::fromLatin1("QList"); + QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QList>"); QTest::newRow("CustomQObject*") << ::qMetaTypeId() << QString::fromLatin1("CustomQObject*"); QTest::newRow("CustomGadget") << ::qMetaTypeId() << QString::fromLatin1("CustomGadget"); diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 4c8d4bf2e7..ad5a8352a6 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -240,7 +240,7 @@ public: */ class MissedBaseline { - friend class QVector; + friend class QList; MissedBaseline() {} // for QVector, don't use public: MissedBaseline(const QString &aId, diff --git a/tests/auto/corelib/tools/CMakeLists.txt b/tests/auto/corelib/tools/CMakeLists.txt index 89fddb33a2..be0c4932c6 100644 --- a/tests/auto/corelib/tools/CMakeLists.txt +++ b/tests/auto/corelib/tools/CMakeLists.txt @@ -16,6 +16,7 @@ add_subdirectory(qfreelist) add_subdirectory(qhash) add_subdirectory(qhashfunctions) add_subdirectory(qline) +add_subdirectory(qlist) add_subdirectory(qmakearray) add_subdirectory(qmap) add_subdirectory(qmargins) @@ -38,7 +39,6 @@ add_subdirectory(qsizef) add_subdirectory(qstl) add_subdirectory(qtimeline) add_subdirectory(qvarlengtharray) -add_subdirectory(qvector) add_subdirectory(qversionnumber) if(APPLE) add_subdirectory(qmacautoreleasepool) diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 8c90822ec8..558c15d441 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -564,7 +564,7 @@ template struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; template -struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; template struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; diff --git a/tests/auto/corelib/tools/qlist/.gitignore b/tests/auto/corelib/tools/qlist/.gitignore new file mode 100644 index 0000000000..5520039486 --- /dev/null +++ b/tests/auto/corelib/tools/qlist/.gitignore @@ -0,0 +1 @@ +tst_qvector diff --git a/tests/auto/corelib/tools/qlist/CMakeLists.txt b/tests/auto/corelib/tools/qlist/CMakeLists.txt new file mode 100644 index 0000000000..fd771de03a --- /dev/null +++ b/tests/auto/corelib/tools/qlist/CMakeLists.txt @@ -0,0 +1,13 @@ +# Generated from qvector.pro. + +##################################################################### +## tst_qvector Test: +##################################################################### + +qt_add_test(tst_qlist + SOURCES + tst_qlist.cpp +) + +## Scopes: +##################################################################### diff --git a/tests/auto/corelib/tools/qlist/qlist.pro b/tests/auto/corelib/tools/qlist/qlist.pro new file mode 100644 index 0000000000..17220f377c --- /dev/null +++ b/tests/auto/corelib/tools/qlist/qlist.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +qtConfig(c++11): CONFIG += c++11 +qtConfig(c++14): CONFIG += c++14 +qtConfig(c++1z): CONFIG += c++1z +TARGET = tst_qlist +QT = core testlib +SOURCES = $$PWD/tst_qlist.cpp diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp new file mode 100644 index 0000000000..df3f2023d6 --- /dev/null +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -0,0 +1,2834 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +struct Movable { + Movable(char input = 'j') + : i(input) + , that(this) + , state(Constructed) + { + counter.fetchAndAddRelaxed(1); + } + Movable(const Movable &other) + : i(other.i) + , that(this) + , state(Constructed) + { + check(other.state, Constructed); + counter.fetchAndAddRelaxed(1); + } + Movable(Movable &&other) + : i(other.i) + , that(other.that) + , state(Constructed) + { + check(other.state, Constructed); + counter.fetchAndAddRelaxed(1); + other.that = nullptr; + } + + ~Movable() + { + check(state, Constructed); + i = 0; + counter.fetchAndAddRelaxed(-1); + state = Destructed; + } + + bool operator ==(const Movable &other) const + { + check(state, Constructed); + check(other.state, Constructed); + return i == other.i; + } + + Movable &operator=(const Movable &other) + { + check(state, Constructed); + check(other.state, Constructed); + i = other.i; + that = this; + return *this; + } + Movable &operator=(Movable &&other) + { + check(state, Constructed); + check(other.state, Constructed); + i = other.i; + that = other.that; + other.that = nullptr; + return *this; + } + bool wasConstructedAt(const Movable *other) const + { + return that == other; + } + char i; + static QAtomicInt counter; +private: + Movable *that; // used to check if an instance was moved + + enum State { Constructed = 106, Destructed = 110 }; + State state; + + static void check(const State state1, const State state2) + { + QCOMPARE(int(state1), int(state2)); + } +}; + +inline size_t qHash(const Movable &key, size_t seed = 0) { return qHash(key.i, seed); } + +QAtomicInt Movable::counter = 0; +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); +QT_END_NAMESPACE +Q_DECLARE_METATYPE(Movable); + +struct Custom { + Custom(char input = 'j') + : i(input) + , that(this) + , state(Constructed) + { + counter.fetchAndAddRelaxed(1); + } + Custom(const Custom &other) + : that(this) + , state(Constructed) + { + check(&other); + counter.fetchAndAddRelaxed(1); + this->i = other.i; + } + ~Custom() + { + check(this); + i = 0; + counter.fetchAndAddRelaxed(-1); + state = Destructed; + } + + bool operator ==(const Custom &other) const + { + check(&other); + check(this); + return i == other.i; + } + + bool operator<(const Custom &other) const + { + check(&other); + check(this); + return i < other.i; + } + + Custom &operator=(const Custom &other) + { + check(&other); + check(this); + i = other.i; + return *this; + } + static QAtomicInt counter; + + char i; // used to identify orgin of an instance +private: + Custom *that; // used to check if an instance was moved + + enum State { Constructed = 106, Destructed = 110 }; + State state; + + static void check(const Custom *c) + { + // check if c object has been moved + QCOMPARE(c, c->that); + QCOMPARE(int(c->state), int(Constructed)); + } +}; +QAtomicInt Custom::counter = 0; + +inline size_t qHash(const Custom &key, size_t seed = 0) { return qHash(key.i, seed); } + +Q_DECLARE_METATYPE(Custom); + +// tests depends on the fact that: +static_assert(!QTypeInfo::isStatic); +static_assert(!QTypeInfo::isComplex); +static_assert(!QTypeInfo::isStatic); +static_assert(QTypeInfo::isComplex); +static_assert(QTypeInfo::isStatic); +static_assert(QTypeInfo::isComplex); + + +class tst_QList : public QObject +{ + Q_OBJECT +private slots: + void constructors_empty() const; + void constructors_emptyReserveZero() const; + void constructors_emptyReserve() const; + void constructors_reserveAndInitialize() const; + void copyConstructorInt() const; + void copyConstructorMovable() const; + void copyConstructorCustom() const; + void assignmentInt() const; + void assignmentMovable() const; + void assignmentCustom() const; + void assignFromInitializerListInt() const; + void assignFromInitializerListMovable() const; + void assignFromInitializerListCustom() const; + void addInt() const; + void addMovable() const; + void addCustom() const; + void appendInt() const; + void appendMovable() const; + void appendCustom() const; + void appendRvalue() const; + void at() const; + void capacityInt() const; + void capacityMovable() const; + void capacityCustom() const; + void clearInt() const; + void clearMovable() const; + void clearCustom() const; + void constData() const; + void constFirst() const; + void constLast() const; + void contains() const; + void countInt() const; + void countMovable() const; + void countCustom() const; + void cpp17ctad() const; + void data() const; + void emptyInt() const; + void emptyMovable() const; + void emptyCustom() const; + void endsWith() const; + void eraseEmptyInt() const; + void eraseEmptyMovable() const; + void eraseEmptyCustom() const; + void eraseEmptyReservedInt() const; + void eraseEmptyReservedMovable() const; + void eraseEmptyReservedCustom() const; + void eraseInt() const; + void eraseIntShared() const; + void eraseMovable() const; + void eraseMovableShared() const; + void eraseCustom() const; + void eraseCustomShared() const; + void eraseReservedInt() const; + void eraseReservedMovable() const; + void eraseReservedCustom() const; + void fillInt() const; + void fillMovable() const; + void fillCustom() const; + void fillDetaches() const; + void first() const; + void fromListInt() const; + void fromListMovable() const; + void fromListCustom() const; + void indexOf() const; + void insertInt() const; + void insertMovable() const; + void insertCustom() const; + void isEmpty() const; + void last() const; + void lastIndexOf() const; + void mid() const; + void moveInt() const; + void moveMovable() const; + void moveCustom() const; + void prependInt() const; + void prependMovable() const; + void prependCustom() const; + void qhashInt() const { qhash(); } + void qhashMovable() const { qhash(); } + void qhashCustom() const { qhash(); } + void removeAllWithAlias() const; + void removeInt() const; + void removeMovable() const; + void removeCustom() const; + void removeFirstLast() const; + void resizePOD_data() const; + void resizePOD() const; + void resizeComplexMovable_data() const; + void resizeComplexMovable() const; + void resizeComplex_data() const; + void resizeComplex() const; + void resizeCtorAndDtor() const; + void reverseIterators() const; + void sizeInt() const; + void sizeMovable() const; + void sizeCustom() const; + void startsWith() const; + void swapInt() const; + void swapMovable() const; + void swapCustom() const; + void toList() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + void fromStdVector() const; + void toStdVector() const; +#endif + void value() const; + + void testOperators() const; + + void reserve(); + void reserveZero(); + void initializeListInt(); + void initializeListMovable(); + void initializeListCustom(); + + void const_shared_null(); + + void detachInt() const; + void detachMovable() const; + void detachCustom() const; + void detachThreadSafetyInt() const; + void detachThreadSafetyMovable() const; + void detachThreadSafetyCustom() const; + + void insertMove() const; + + void swapItemsAt() const; + + void emplaceInt(); + void emplaceCustom(); + void emplaceMovable(); + void emplaceConsistentWithStdVectorInt(); + void emplaceConsistentWithStdVectorCustom(); + void emplaceConsistentWithStdVectorMovable(); + void emplaceReturnsIterator(); + void emplaceBack(); + void emplaceBackReturnsRef(); + void emplaceWithElementFromTheSameContainer(); + void emplaceWithElementFromTheSameContainer_data(); + +private: + template void copyConstructor() const; + template void add() const; + template void append() const; + template void assignFromInitializerList() const; + template void capacity() const; + template void clear() const; + template void count() const; + template void empty() const; + template void eraseEmpty() const; + template void eraseEmptyReserved() const; + template void erase(bool shared) const; + template void eraseReserved() const; + template void fill() const; + template void fromList() const; + template void insert() const; + template void qhash() const; + template void move() const; + template void prepend() const; + template void remove() const; + template void size() const; + template void swap() const; + template void initializeList(); + template void detach() const; + template void detachThreadSafety() const; + template void emplaceImpl() const; + template void emplaceConsistentWithStdVectorImpl() const; +}; + + +template struct SimpleValue +{ + static T at(int index) + { + return Values[index % MaxIndex]; + } + + static QList vector(int size) + { + QList ret; + for (int i = 0; i < size; i++) + ret.append(at(i)); + return ret; + } + + static const uint MaxIndex = 6; + static const T Values[MaxIndex]; +}; + +template<> +const int SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; +template<> +const Movable SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; +template<> +const Custom SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; + +// Make some macros for the tests to use in order to be slightly more readable... +#define T_FOO SimpleValue::at(0) +#define T_BAR SimpleValue::at(1) +#define T_BAZ SimpleValue::at(2) +#define T_CAT SimpleValue::at(3) +#define T_DOG SimpleValue::at(4) +#define T_BLAH SimpleValue::at(5) + +void tst_QList::constructors_empty() const +{ + QList emptyInt; + QList emptyMovable; + QList emptyCustom; +} + +void tst_QList::constructors_emptyReserveZero() const +{ + QList emptyInt(0); + QList emptyMovable(0); + QList emptyCustom(0); +} + +void tst_QList::constructors_emptyReserve() const +{ + // pre-reserve capacity + QList myInt(5); + QVERIFY(myInt.capacity() == 5); + QList myMovable(5); + QVERIFY(myMovable.capacity() == 5); + QList myCustom(4); + QVERIFY(myCustom.capacity() == 4); +} + +void tst_QList::constructors_reserveAndInitialize() const +{ + // default-initialise items + + QList myInt(5, 42); + QVERIFY(myInt.capacity() == 5); + foreach (int meaningoflife, myInt) { + QCOMPARE(meaningoflife, 42); + } + + QList myString(5, QString::fromLatin1("c++")); + QVERIFY(myString.capacity() == 5); + // make sure all items are initialised ok + foreach (QString meaningoflife, myString) { + QCOMPARE(meaningoflife, QString::fromLatin1("c++")); + } + + QList myCustom(5, Custom('n')); + QVERIFY(myCustom.capacity() == 5); + // make sure all items are initialised ok + foreach (Custom meaningoflife, myCustom) { + QCOMPARE(meaningoflife.i, 'n'); + } +} + +template +void tst_QList::copyConstructor() const +{ + T value1(SimpleValue::at(0)); + T value2(SimpleValue::at(1)); + T value3(SimpleValue::at(2)); + T value4(SimpleValue::at(3)); + { + QList v1; + QList v2(v1); + QCOMPARE(v1, v2); + } + { + QList v1; + v1 << value1 << value2 << value3 << value4; + QList v2(v1); + QCOMPARE(v1, v2); + } +} + +void tst_QList::copyConstructorInt() const +{ + copyConstructor(); +} + +void tst_QList::copyConstructorMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + copyConstructor(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::copyConstructorCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + copyConstructor(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +static inline void testAssignment() +{ + QList v1(5); + QCOMPARE(v1.size(), 5); + QVERIFY(v1.isDetached()); + + QList v2(7); + QCOMPARE(v2.size(), 7); + QVERIFY(v2.isDetached()); + + QVERIFY(!v1.isSharedWith(v2)); + + v1 = v2; + + QVERIFY(!v1.isDetached()); + QVERIFY(!v2.isDetached()); + QVERIFY(v1.isSharedWith(v2)); + + const void *const data1 = v1.constData(); + const void *const data2 = v2.constData(); + + QCOMPARE(data1, data2); + + v1.clear(); + + QVERIFY(v2.isDetached()); + QVERIFY(!v1.isSharedWith(v2)); + QCOMPARE((void *)v2.constData(), data2); +} + +void tst_QList::assignmentInt() const +{ + testAssignment(); +} + +void tst_QList::assignmentMovable() const +{ + testAssignment(); +} + +void tst_QList::assignmentCustom() const +{ + testAssignment(); +} + +template +void tst_QList::assignFromInitializerList() const +{ + T val1(SimpleValue::at(1)); + T val2(SimpleValue::at(2)); + T val3(SimpleValue::at(3)); + + QList v1 = {val1, val2, val3}; + QCOMPARE(v1, QList() << val1 << val2 << val3); + QCOMPARE(v1, (QList {val1, val2, val3})); + + v1 = {}; + QCOMPARE(v1.size(), 0); +} + +void tst_QList::assignFromInitializerListInt() const +{ + assignFromInitializerList(); +} + +void tst_QList::assignFromInitializerListMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + assignFromInitializerList(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::assignFromInitializerListCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + assignFromInitializerList(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::add() const +{ + { + QList empty1; + QList empty2; + QVERIFY((empty1 + empty2).isEmpty()); + empty1 += empty2; + QVERIFY(empty1.isEmpty()); + QVERIFY(empty2.isEmpty()); + } + { + QList v(12); + QList empty; + QCOMPARE((v + empty), v); + v += empty; + QVERIFY(!v.isEmpty()); + QCOMPARE(v.size(), 12); + QVERIFY(empty.isEmpty()); + } + { + QList v1(12); + QList v2; + v2 += v1; + QVERIFY(!v1.isEmpty()); + QCOMPARE(v1.size(), 12); + QVERIFY(!v2.isEmpty()); + QCOMPARE(v2.size(), 12); + } +} + +void tst_QList::addInt() const +{ + add(); +} + +void tst_QList::addMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + add(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::addCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + add(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::append() const +{ + { + QList myvec; + myvec.append(SimpleValue::at(0)); + QVERIFY(myvec.size() == 1); + myvec.append(SimpleValue::at(1)); + QVERIFY(myvec.size() == 2); + myvec.append(SimpleValue::at(2)); + QVERIFY(myvec.size() == 3); + + QCOMPARE(myvec, QList() << SimpleValue::at(0) + << SimpleValue::at(1) + << SimpleValue::at(2)); + } + { + QList v(2); + v.append(SimpleValue::at(0)); + QVERIFY(v.size() == 3); + QCOMPARE(v.at(v.size() - 1), SimpleValue::at(0)); + } + { + QList v(2); + v.reserve(12); + v.append(SimpleValue::at(0)); + QVERIFY(v.size() == 3); + QCOMPARE(v.at(v.size() - 1), SimpleValue::at(0)); + } + { + QList v; + v << 1 << 2 << 3; + QList x; + x << 4 << 5 << 6; + v.append(x); + + QList combined; + combined << 1 << 2 << 3 << 4 << 5 << 6; + + QCOMPARE(v, combined); + } +} + +void tst_QList::appendInt() const +{ + append(); +} + +void tst_QList::appendMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + append(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::appendCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + append(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::appendRvalue() const +{ + QList v; + v.append("hello"); + QString world = "world"; + v.append(std::move(world)); + QVERIFY(world.isEmpty()); + QCOMPARE(v.front(), QString("hello")); + QCOMPARE(v.back(), QString("world")); +} + +void tst_QList::at() const +{ + QList myvec; + myvec << "foo" << "bar" << "baz"; + + QVERIFY(myvec.size() == 3); + QCOMPARE(myvec.at(0), QLatin1String("foo")); + QCOMPARE(myvec.at(1), QLatin1String("bar")); + QCOMPARE(myvec.at(2), QLatin1String("baz")); + + // append an item + myvec << "hello"; + QVERIFY(myvec.size() == 4); + QCOMPARE(myvec.at(0), QLatin1String("foo")); + QCOMPARE(myvec.at(1), QLatin1String("bar")); + QCOMPARE(myvec.at(2), QLatin1String("baz")); + QCOMPARE(myvec.at(3), QLatin1String("hello")); + + // remove an item + myvec.remove(1); + QVERIFY(myvec.size() == 3); + QCOMPARE(myvec.at(0), QLatin1String("foo")); + QCOMPARE(myvec.at(1), QLatin1String("baz")); + QCOMPARE(myvec.at(2), QLatin1String("hello")); +} + +template +void tst_QList::capacity() const +{ + QList myvec; + + // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a + // few items isn't an entirely unforseeable possibility. + QVERIFY(myvec.capacity() == 0); + + // test it gets a size + myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); + QVERIFY(myvec.capacity() >= 3); + + // make sure it grows ok + myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); + QVERIFY(myvec.capacity() >= 6); + // let's try squeeze a bit + myvec.remove(3); + myvec.remove(3); + myvec.remove(3); + myvec.squeeze(); + QVERIFY(myvec.capacity() >= 3); + + myvec.remove(0); + myvec.remove(0); + myvec.remove(0); + myvec.squeeze(); + QVERIFY(myvec.capacity() == 0); +} + +void tst_QList::capacityInt() const +{ + capacity(); +} + +void tst_QList::capacityMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + capacity(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::capacityCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + capacity(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::clear() const +{ + QList myvec; + myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); + + const auto oldCapacity = myvec.capacity(); + QCOMPARE(myvec.size(), 3); + myvec.clear(); + QCOMPARE(myvec.size(), 0); + QCOMPARE(myvec.capacity(), oldCapacity); +} + +void tst_QList::clearInt() const +{ + clear(); +} + +void tst_QList::clearMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + clear(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::clearCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + clear(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::constData() const +{ + int arr[] = { 42, 43, 44 }; + QList myvec; + myvec << 42 << 43 << 44; + + QVERIFY(memcmp(myvec.constData(), reinterpret_cast(&arr), sizeof(int) * 3) == 0); +} + +void tst_QList::contains() const +{ + QList myvec; + myvec << "aaa" << "bbb" << "ccc"; + + QVERIFY(myvec.contains(QLatin1String("aaa"))); + QVERIFY(myvec.contains(QLatin1String("bbb"))); + QVERIFY(myvec.contains(QLatin1String("ccc"))); + QVERIFY(!myvec.contains(QLatin1String("I don't exist"))); + + // add it and make sure it does :) + myvec.append(QLatin1String("I don't exist")); + QVERIFY(myvec.contains(QLatin1String("I don't exist"))); +} + +template +void tst_QList::count() const +{ + // total size + { + // zero size + QList myvec; + QVERIFY(myvec.count() == 0); + + // grow + myvec.append(SimpleValue::at(0)); + QVERIFY(myvec.count() == 1); + myvec.append(SimpleValue::at(1)); + QVERIFY(myvec.count() == 2); + + // shrink + myvec.remove(0); + QVERIFY(myvec.count() == 1); + myvec.remove(0); + QVERIFY(myvec.count() == 0); + } + + // count of items + { + QList myvec; + myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); + + // initial tests + QVERIFY(myvec.count(SimpleValue::at(0)) == 1); + QVERIFY(myvec.count(SimpleValue::at(3)) == 0); + + // grow + myvec.append(SimpleValue::at(0)); + QVERIFY(myvec.count(SimpleValue::at(0)) == 2); + + // shrink + myvec.remove(0); + QVERIFY(myvec.count(SimpleValue::at(0)) == 1); + } +} + +void tst_QList::countInt() const +{ + count(); +} + +void tst_QList::countMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + count(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::countCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + count(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::cpp17ctad() const +{ +#ifdef __cpp_deduction_guides +#define QVERIFY_IS_VECTOR_OF(obj, Type) \ + QVERIFY2((std::is_same>::value), \ + QMetaType::typeName(qMetaTypeId())) +#define CHECK(Type, One, Two, Three) \ + do { \ + const Type v[] = {One, Two, Three}; \ + QList v1 = {One, Two, Three}; \ + QVERIFY_IS_VECTOR_OF(v1, Type); \ + QList v2(v1.begin(), v1.end()); \ + QVERIFY_IS_VECTOR_OF(v2, Type); \ + QList v3(std::begin(v), std::end(v)); \ + QVERIFY_IS_VECTOR_OF(v3, Type); \ + } while (false) \ + /*end*/ + CHECK(int, 1, 2, 3); + CHECK(double, 1.0, 2.0, 3.0); + CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three")); +#undef QVERIFY_IS_VECTOR_OF +#undef CHECK +#else + QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler."); +#endif +} + +void tst_QList::data() const +{ + QList myvec; + myvec << 42 << 43 << 44; + + // make sure it starts off ok + QCOMPARE(*(myvec.data() + 1), 43); + + // alter it + *(myvec.data() + 1) = 69; + + // check it altered + QCOMPARE(*(myvec.data() + 1), 69); + + int arr[] = { 42, 69, 44 }; + QVERIFY(memcmp(myvec.data(), reinterpret_cast(&arr), sizeof(int) * 3) == 0); +} + +template +void tst_QList::empty() const +{ + QList myvec; + + // starts empty + QVERIFY(myvec.empty()); + + // not empty + myvec.append(SimpleValue::at(2)); + QVERIFY(!myvec.empty()); + + // empty again + myvec.remove(0); + QVERIFY(myvec.empty()); +} + +void tst_QList::emptyInt() const +{ + empty(); +} + +void tst_QList::emptyMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + empty(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::emptyCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + empty(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::endsWith() const +{ + QList myvec; + + // empty vector + QVERIFY(!myvec.endsWith(1)); + + // add the one, should work + myvec.append(1); + QVERIFY(myvec.endsWith(1)); + + // add something else, fails now + myvec.append(3); + QVERIFY(!myvec.endsWith(1)); + + // remove it again :) + myvec.remove(1); + QVERIFY(myvec.endsWith(1)); +} + +template +void tst_QList::eraseEmpty() const +{ + QList v; + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); +} + +void tst_QList::eraseEmptyInt() const +{ + eraseEmpty(); +} + +void tst_QList::eraseEmptyMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + eraseEmpty(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::eraseEmptyCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + eraseEmpty(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::eraseEmptyReserved() const +{ + QList v; + v.reserve(10); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); +} + +void tst_QList::eraseEmptyReservedInt() const +{ + eraseEmptyReserved(); +} + +void tst_QList::eraseEmptyReservedMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + eraseEmptyReserved(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::eraseEmptyReservedCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + eraseEmptyReserved(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +struct SharedVectorChecker +{ + SharedVectorChecker(const QList &original, bool doCopyVector) + : originalSize(-1), + copy(0) + { + if (doCopyVector) { + originalSize = original.size(); + copy = new QList(original); + // this is unlikely to fail, but if the check in the destructor fails it's good to know that + // we were still alright here. + QCOMPARE(originalSize, copy->size()); + } + } + + ~SharedVectorChecker() + { + if (copy) + QCOMPARE(copy->size(), originalSize); + delete copy; + } + + int originalSize; + QList *copy; +}; + +template +void tst_QList::erase(bool shared) const +{ + // note: remove() is actually more efficient, and more dangerous, because it uses the non-detaching + // begin() / end() internally. you can also use constBegin() and constEnd() with erase(), but only + // using reinterpret_cast... because both iterator types are really just pointers. + // so we use a mix of erase() and remove() to cover more cases. + { + QList v = SimpleValue::vector(12); + SharedVectorChecker svc(v, shared); + v.erase(v.begin()); + QCOMPARE(v.size(), 11); + for (int i = 0; i < 11; i++) + QCOMPARE(v.at(i), SimpleValue::at(i + 1)); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); + if (shared) + QCOMPARE(SimpleValue::vector(12), *svc.copy); + } + { + QList v = SimpleValue::vector(12); + SharedVectorChecker svc(v, shared); + v.remove(1); + QCOMPARE(v.size(), 11); + QCOMPARE(v.at(0), SimpleValue::at(0)); + for (int i = 1; i < 11; i++) + QCOMPARE(v.at(i), SimpleValue::at(i + 1)); + v.erase(v.begin() + 1, v.end()); + QCOMPARE(v.size(), 1); + QCOMPARE(v.at(0), SimpleValue::at(0)); + if (shared) + QCOMPARE(SimpleValue::vector(12), *svc.copy); + } + { + QList v = SimpleValue::vector(12); + SharedVectorChecker svc(v, shared); + v.erase(v.begin(), v.end() - 1); + QCOMPARE(v.size(), 1); + QCOMPARE(v.at(0), SimpleValue::at(11)); + if (shared) + QCOMPARE(SimpleValue::vector(12), *svc.copy); + } + { + QList v = SimpleValue::vector(12); + SharedVectorChecker svc(v, shared); + v.remove(5); + QCOMPARE(v.size(), 11); + for (int i = 0; i < 5; i++) + QCOMPARE(v.at(i), SimpleValue::at(i)); + for (int i = 5; i < 11; i++) + QCOMPARE(v.at(i), SimpleValue::at(i + 1)); + v.erase(v.begin() + 1, v.end() - 1); + QCOMPARE(v.at(0), SimpleValue::at(0)); + QCOMPARE(v.at(1), SimpleValue::at(11)); + QCOMPARE(v.size(), 2); + if (shared) + QCOMPARE(SimpleValue::vector(12), *svc.copy); + } +} + +void tst_QList::eraseInt() const +{ + erase(false); +} + +void tst_QList::eraseIntShared() const +{ + erase(true); +} + +void tst_QList::eraseMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + erase(false); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::eraseMovableShared() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + erase(true); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::eraseCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + erase(false); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::eraseCustomShared() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + erase(true); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template void tst_QList::eraseReserved() const +{ + { + QList v(12); + v.reserve(16); + v.erase(v.begin()); + QCOMPARE(v.size(), 11); + v.erase(v.begin(), v.end()); + QCOMPARE(v.size(), 0); + } + { + QList v(12); + v.reserve(16); + v.erase(v.begin() + 1); + QCOMPARE(v.size(), 11); + v.erase(v.begin() + 1, v.end()); + QCOMPARE(v.size(), 1); + } + { + QList v(12); + v.reserve(16); + v.erase(v.begin(), v.end() - 1); + QCOMPARE(v.size(), 1); + } + { + QList v(12); + v.reserve(16); + v.erase(v.begin() + 5); + QCOMPARE(v.size(), 11); + v.erase(v.begin() + 1, v.end() - 1); + QCOMPARE(v.size(), 2); + } +} + +void tst_QList::eraseReservedInt() const +{ + eraseReserved(); +} + +void tst_QList::eraseReservedMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + eraseReserved(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::eraseReservedCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + eraseReserved(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::fill() const +{ + QList myvec; + + // resize + myvec.resize(5); + myvec.fill(SimpleValue::at(1)); + QCOMPARE(myvec, QList() << SimpleValue::at(1) << SimpleValue::at(1) + << SimpleValue::at(1) << SimpleValue::at(1) + << SimpleValue::at(1)); + + // make sure it can resize itself too + myvec.fill(SimpleValue::at(2), 10); + QCOMPARE(myvec, QList() << SimpleValue::at(2) << SimpleValue::at(2) + << SimpleValue::at(2) << SimpleValue::at(2) + << SimpleValue::at(2) << SimpleValue::at(2) + << SimpleValue::at(2) << SimpleValue::at(2) + << SimpleValue::at(2) << SimpleValue::at(2)); +} + +void tst_QList::fillInt() const +{ + fill(); +} + +void tst_QList::fillMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + fill(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::fillCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + fill(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::fillDetaches() const +{ + QList test = { 1, 2, 3 }; + QList copy = test; + copy.fill(42); + + QCOMPARE(test, QList({1, 2, 3})); + QCOMPARE(copy, QList({42, 42, 42})); +} + +void tst_QList::first() const +{ + QList myvec; + myvec << 69 << 42 << 3; + + // test it starts ok + QCOMPARE(myvec.first(), 69); + QCOMPARE(myvec.constFirst(), 69); + + // test removal changes + myvec.remove(0); + QCOMPARE(myvec.first(), 42); + QCOMPARE(myvec.constFirst(), 42); + + // test prepend changes + myvec.prepend(23); + QCOMPARE(myvec.first(), 23); + QCOMPARE(myvec.constFirst(), 23); +} + +void tst_QList::constFirst() const +{ + QList myvec; + myvec << 69 << 42 << 3; + + // test it starts ok + QCOMPARE(myvec.constFirst(), 69); + QVERIFY(myvec.isDetached()); + + QList myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constFirst(), 69); + QCOMPARE(myvecCopy.constFirst(), 69); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + // test removal changes + myvec.remove(0); + QVERIFY(myvec.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QCOMPARE(myvec.constFirst(), 42); + QCOMPARE(myvecCopy.constFirst(), 69); + + myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constFirst(), 42); + QCOMPARE(myvecCopy.constFirst(), 42); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + // test prepend changes + myvec.prepend(23); + QVERIFY(myvec.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QCOMPARE(myvec.constFirst(), 23); + QCOMPARE(myvecCopy.constFirst(), 42); + + myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constFirst(), 23); + QCOMPARE(myvecCopy.constFirst(), 23); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); +} + + +template +void tst_QList::fromList() const +{ + QList list; + list << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3); + + QList myvec; + myvec = QList::fromList(list); + + // test it worked ok + QCOMPARE(myvec, QList() << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3)); + QCOMPARE(list, QList() << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3)); +} + +void tst_QList::fromListInt() const +{ + fromList(); +} + +void tst_QList::fromListMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + fromList(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::fromListCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + fromList(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +void tst_QList::fromStdVector() const +{ + // stl = :( + std::vector svec; + svec.push_back(QLatin1String("aaa")); + svec.push_back(QLatin1String("bbb")); + svec.push_back(QLatin1String("ninjas")); + svec.push_back(QLatin1String("pirates")); + QList myvec = QList::fromStdVector(svec); + + // test it converts ok + QCOMPARE(myvec, QList() << "aaa" << "bbb" << "ninjas" << "pirates"); +} +#endif + +void tst_QList::indexOf() const +{ + QList myvec; + myvec << "A" << "B" << "C" << "B" << "A"; + + QVERIFY(myvec.indexOf("B") == 1); + QVERIFY(myvec.indexOf("B", 1) == 1); + QVERIFY(myvec.indexOf("B", 2) == 3); + QVERIFY(myvec.indexOf("X") == -1); + QVERIFY(myvec.indexOf("X", 2) == -1); + + // add an X + myvec << "X"; + QVERIFY(myvec.indexOf("X") == 5); + QVERIFY(myvec.indexOf("X", 5) == 5); + QVERIFY(myvec.indexOf("X", 6) == -1); + + // remove first A + myvec.remove(0); + QVERIFY(myvec.indexOf("A") == 3); + QVERIFY(myvec.indexOf("A", 3) == 3); + QVERIFY(myvec.indexOf("A", 4) == -1); +} + +template +void tst_QList::insert() const +{ + QList myvec; + const T + tA = SimpleValue::at(0), + tB = SimpleValue::at(1), + tC = SimpleValue::at(2), + tX = SimpleValue::at(3), + tZ = SimpleValue::at(4), + tT = SimpleValue::at(5), + ti = SimpleValue::at(6); + myvec << tA << tB << tC; + QList myvec2 = myvec; + + // first position + QCOMPARE(myvec.at(0), tA); + myvec.insert(0, tX); + QCOMPARE(myvec.at(0), tX); + QCOMPARE(myvec.at(1), tA); + + QCOMPARE(myvec2.at(0), tA); + myvec2.insert(myvec2.begin(), tX); + QCOMPARE(myvec2.at(0), tX); + QCOMPARE(myvec2.at(1), tA); + + // middle + myvec.insert(1, tZ); + QCOMPARE(myvec.at(0), tX); + QCOMPARE(myvec.at(1), tZ); + QCOMPARE(myvec.at(2), tA); + + myvec2.insert(myvec2.begin() + 1, tZ); + QCOMPARE(myvec2.at(0), tX); + QCOMPARE(myvec2.at(1), tZ); + QCOMPARE(myvec2.at(2), tA); + + // end + myvec.insert(5, tT); + QCOMPARE(myvec.at(5), tT); + QCOMPARE(myvec.at(4), tC); + + myvec2.insert(myvec2.end(), tT); + QCOMPARE(myvec2.at(5), tT); + QCOMPARE(myvec2.at(4), tC); + + // insert a lot of garbage in the middle + myvec.insert(2, 2, ti); + QCOMPARE(myvec, QList() << tX << tZ << ti << ti + << tA << tB << tC << tT); + + myvec2.insert(myvec2.begin() + 2, 2, ti); + QCOMPARE(myvec2, myvec); + + // insert from references to the same container: + myvec.insert(0, 1, myvec[5]); // inserts tB + myvec2.insert(0, 1, myvec2[5]); // inserts tB + QCOMPARE(myvec, QList() << tB << tX << tZ << ti << ti + << tA << tB << tC << tT); + QCOMPARE(myvec2, myvec); + + myvec.insert(0, 1, const_cast&>(myvec)[0]); // inserts tB + myvec2.insert(0, 1, const_cast&>(myvec2)[0]); // inserts tB + QCOMPARE(myvec, QList() << tB << tB << tX << tZ << ti << ti + << tA << tB << tC << tT); + QCOMPARE(myvec2, myvec); +} + +void tst_QList::insertInt() const +{ + insert(); +} + +void tst_QList::insertMovable() const +{ + insert(); +} + +void tst_QList::insertCustom() const +{ + insert(); +} + +void tst_QList::isEmpty() const +{ + QList myvec; + + // starts ok + QVERIFY(myvec.isEmpty()); + + // not empty now + myvec.append(QLatin1String("hello there")); + QVERIFY(!myvec.isEmpty()); + + // empty again + myvec.remove(0); + QVERIFY(myvec.isEmpty()); +} + +void tst_QList::last() const +{ + QList myvec; + myvec << "A" << "B" << "C"; + + // test starts ok + QCOMPARE(myvec.last(), QLatin1String("C")); + QCOMPARE(myvec.constLast(), QLatin1String("C")); + + // test it changes ok + myvec.append(QLatin1String("X")); + QCOMPARE(myvec.last(), QLatin1String("X")); + QCOMPARE(myvec.constLast(), QLatin1String("X")); + + // and remove again + myvec.remove(3); + QCOMPARE(myvec.last(), QLatin1String("C")); + QCOMPARE(myvec.constLast(), QLatin1String("C")); +} + +void tst_QList::constLast() const +{ + QList myvec; + myvec << 69 << 42 << 3; + + // test it starts ok + QCOMPARE(myvec.constLast(), 3); + QVERIFY(myvec.isDetached()); + + QList myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constLast(), 3); + QCOMPARE(myvecCopy.constLast(), 3); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + // test removal changes + myvec.removeLast(); + QVERIFY(myvec.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QCOMPARE(myvec.constLast(), 42); + QCOMPARE(myvecCopy.constLast(), 3); + + myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constLast(), 42); + QCOMPARE(myvecCopy.constLast(), 42); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + // test prepend changes + myvec.append(23); + QVERIFY(myvec.isDetached()); + QVERIFY(!myvec.isSharedWith(myvecCopy)); + QCOMPARE(myvec.constLast(), 23); + QCOMPARE(myvecCopy.constLast(), 42); + + myvecCopy = myvec; + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); + + QCOMPARE(myvec.constLast(), 23); + QCOMPARE(myvecCopy.constLast(), 23); + + QVERIFY(!myvec.isDetached()); + QVERIFY(!myvecCopy.isDetached()); + QVERIFY(myvec.isSharedWith(myvecCopy)); + QVERIFY(myvecCopy.isSharedWith(myvec)); +} + +void tst_QList::lastIndexOf() const +{ + QList myvec; + myvec << "A" << "B" << "C" << "B" << "A"; + + QVERIFY(myvec.lastIndexOf("B") == 3); + QVERIFY(myvec.lastIndexOf("B", 2) == 1); + QVERIFY(myvec.lastIndexOf("X") == -1); + QVERIFY(myvec.lastIndexOf("X", 2) == -1); + + // add an X + myvec << "X"; + QVERIFY(myvec.lastIndexOf("X") == 5); + QVERIFY(myvec.lastIndexOf("X", 5) == 5); + QVERIFY(myvec.lastIndexOf("X", 3) == -1); + + // remove first A + myvec.remove(0); + QVERIFY(myvec.lastIndexOf("A") == 3); + QVERIFY(myvec.lastIndexOf("A", 3) == 3); + QVERIFY(myvec.lastIndexOf("A", 2) == -1); +} + +void tst_QList::mid() const +{ + QList list; + list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty"; + + QCOMPARE(list.mid(3, 3), QList() << "bak" << "buck" << "hello"); + QCOMPARE(list.mid(6, 10), QList() << "kitty"); + QCOMPARE(list.mid(-1, 20), list); + QCOMPARE(list.mid(4), QList() << "buck" << "hello" << "kitty"); +} + +template +void tst_QList::qhash() const +{ + QList l1, l2; + QCOMPARE(qHash(l1), qHash(l2)); + l1 << SimpleValue::at(0); + l2 << SimpleValue::at(0); + QCOMPARE(qHash(l1), qHash(l2)); +} + +template +void tst_QList::move() const +{ + QList list; + list << T_FOO << T_BAR << T_BAZ; + + // move an item + list.move(0, list.count() - 1); + QCOMPARE(list, QList() << T_BAR << T_BAZ << T_FOO); + + // move it back + list.move(list.count() - 1, 0); + QCOMPARE(list, QList() << T_FOO << T_BAR << T_BAZ); + + // move an item in the middle + list.move(1, 0); + QCOMPARE(list, QList() << T_BAR << T_FOO << T_BAZ); +} + +void tst_QList::moveInt() const +{ + move(); +} + +void tst_QList::moveMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + move(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::moveCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + move(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +template +void tst_QList::prepend() const +{ + QList myvec; + T val1 = SimpleValue::at(0); + T val2 = SimpleValue::at(1); + T val3 = SimpleValue::at(2); + T val4 = SimpleValue::at(3); + T val5 = SimpleValue::at(4); + myvec << val1 << val2 << val3; + + // starts ok + QVERIFY(myvec.size() == 3); + QCOMPARE(myvec.at(0), val1); + + // add something + myvec.prepend(val4); + QCOMPARE(myvec.at(0), val4); + QCOMPARE(myvec.at(1), val1); + QVERIFY(myvec.size() == 4); + + // something else + myvec.prepend(val5); + QCOMPARE(myvec.at(0), val5); + QCOMPARE(myvec.at(1), val4); + QCOMPARE(myvec.at(2), val1); + QVERIFY(myvec.size() == 5); + + // clear and prepend to an empty vector + myvec.clear(); + QVERIFY(myvec.size() == 0); + myvec.prepend(val5); + QVERIFY(myvec.size() == 1); + QCOMPARE(myvec.at(0), val5); +} + +void tst_QList::prependInt() const +{ + prepend(); +} + +void tst_QList::prependMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + prepend(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::prependCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + prepend(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::removeAllWithAlias() const +{ + QList strings; + strings << "One" << "Two" << "Three" << "One" /* must be distinct, but equal */; + QCOMPARE(strings.removeAll(strings.front()), 2); // will trigger asan/ubsan +} + +template +void tst_QList::remove() const +{ + QList myvec; + T val1 = SimpleValue::at(1); + T val2 = SimpleValue::at(2); + T val3 = SimpleValue::at(3); + T val4 = SimpleValue::at(4); + myvec << val1 << val2 << val3; + myvec << val1 << val2 << val3; + myvec << val1 << val2 << val3; + // remove middle + myvec.remove(1); + QCOMPARE(myvec, QList() << val1 << val3 << val1 << val2 << val3 << val1 << val2 << val3); + + // removeOne() + QVERIFY(!myvec.removeOne(val4)); + QVERIFY(myvec.removeOne(val2)); + QCOMPARE(myvec, QList() << val1 << val3 << val1 << val3 << val1 << val2 << val3); + + QList myvecCopy = myvec; + QVERIFY(myvecCopy.isSharedWith(myvec)); + // removeAll() + QCOMPARE(myvec.removeAll(val4), 0); + QVERIFY(myvecCopy.isSharedWith(myvec)); + QCOMPARE(myvec.removeAll(val1), 3); + QVERIFY(!myvecCopy.isSharedWith(myvec)); + QCOMPARE(myvec, QList() << val3 << val3 << val2 << val3); + myvecCopy = myvec; + QVERIFY(myvecCopy.isSharedWith(myvec)); + QCOMPARE(myvec.removeAll(val2), 1); + QVERIFY(!myvecCopy.isSharedWith(myvec)); + QCOMPARE(myvec, QList() << val3 << val3 << val3); + + // remove rest + myvec.remove(0, 3); + QCOMPARE(myvec, QList()); +} + +void tst_QList::removeInt() const +{ + remove(); +} + +void tst_QList::removeMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + remove(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::removeCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + remove(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +struct RemoveLastTestClass +{ + RemoveLastTestClass() { other = 0; deleted = false; } + RemoveLastTestClass *other; + bool deleted; + ~RemoveLastTestClass() + { + deleted = true; + if (other) + other->other = 0; + } +}; + +void tst_QList::removeFirstLast() const +{ + // pop_pack - pop_front + QList t, t2; + t.append(1); + t.append(2); + t.append(3); + t.append(4); + t2 = t; + t.pop_front(); + QCOMPARE(t.size(), 3); + QCOMPARE(t.at(0), 2); + t.pop_back(); + QCOMPARE(t.size(), 2); + QCOMPARE(t.at(0), 2); + QCOMPARE(t.at(1), 3); + + // takefirst - takeLast + int n1 = t2.takeLast(); + QCOMPARE(t2.size(), 3); + QCOMPARE(n1, 4); + QCOMPARE(t2.at(0), 1); + QCOMPARE(t2.at(2), 3); + n1 = t2.takeFirst(); + QCOMPARE(t2.size(), 2); + QCOMPARE(n1, 1); + QCOMPARE(t2.at(0), 2); + QCOMPARE(t2.at(1), 3); + + // remove first + QList x, y; + x.append(1); + x.append(2); + y = x; + x.removeFirst(); + QCOMPARE(x.size(), 1); + QCOMPARE(y.size(), 2); + QCOMPARE(x.at(0), 2); + + // remove Last + QList v; + v.resize(2); + v[0].other = &(v[1]); + v[1].other = &(v[0]); + // Check dtor - complex type + QVERIFY(v.at(0).other != 0); + v.removeLast(); + QVERIFY(v.at(0).other == 0); + QCOMPARE(v.at(0).deleted, false); + // check iterator + int count = 0; + for (QList::const_iterator i = v.constBegin(); i != v.constEnd(); ++i) { + ++count; + QVERIFY(i->other == 0); + QCOMPARE(i->deleted, false); + } + // Check size + QCOMPARE(count, 1); + QCOMPARE(v.size(), 1); + v.removeLast(); + QCOMPARE(v.size(), 0); + // Check if we do correct realloc + QList v2, v3; + v2.append(1); + v2.append(2); + v3 = v2; // shared + v2.removeLast(); + QCOMPARE(v2.size(), 1); + QCOMPARE(v3.size(), 2); + QCOMPARE(v2.at(0), 1); + QCOMPARE(v3.at(0), 1); + QCOMPARE(v3.at(1), 2); + + // Remove last with shared + QList z1, z2; + z1.append(9); + z2 = z1; + z1.removeLast(); + QCOMPARE(z1.size(), 0); + QCOMPARE(z2.size(), 1); + QCOMPARE(z2.at(0), 9); +} + + +void tst_QList::resizePOD_data() const +{ + QTest::addColumn >("vector"); + QTest::addColumn("size"); + + QVERIFY(!QTypeInfo::isComplex); + QVERIFY(!QTypeInfo::isStatic); + + QList null; + QList empty(0, 5); + QList emptyReserved; + QList nonEmpty; + QList nonEmptyReserved; + + emptyReserved.reserve(10); + nonEmptyReserved.reserve(15); + nonEmpty << 0 << 1 << 2 << 3 << 4; + nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6; + QVERIFY(emptyReserved.capacity() >= 10); + QVERIFY(nonEmptyReserved.capacity() >= 15); + + QTest::newRow("null") << null << 10; + QTest::newRow("empty") << empty << 10; + QTest::newRow("emptyReserved") << emptyReserved << 10; + QTest::newRow("nonEmpty") << nonEmpty << 10; + QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; +} + +void tst_QList::resizePOD() const +{ + QFETCH(QList, vector); + QFETCH(int, size); + + const int oldSize = vector.size(); + + vector.resize(size); + QCOMPARE(vector.size(), size); + QVERIFY(vector.capacity() >= size); + for (int i = oldSize; i < size; ++i) + QVERIFY(vector[i] == 0); // check initialization + + const int capacity = vector.capacity(); + + vector.clear(); + QCOMPARE(vector.size(), 0); + QVERIFY(vector.capacity() <= capacity); +} + +void tst_QList::resizeComplexMovable_data() const +{ + QTest::addColumn >("vector"); + QTest::addColumn("size"); + + QVERIFY(QTypeInfo::isComplex); + QVERIFY(!QTypeInfo::isStatic); + + QList null; + QList empty(0, 'Q'); + QList emptyReserved; + QList nonEmpty; + QList nonEmptyReserved; + + emptyReserved.reserve(10); + nonEmptyReserved.reserve(15); + nonEmpty << '0' << '1' << '2' << '3' << '4'; + nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; + QVERIFY(emptyReserved.capacity() >= 10); + QVERIFY(nonEmptyReserved.capacity() >= 15); + + QTest::newRow("null") << null << 10; + QTest::newRow("empty") << empty << 10; + QTest::newRow("emptyReserved") << emptyReserved << 10; + QTest::newRow("nonEmpty") << nonEmpty << 10; + QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; +} + +void tst_QList::resizeComplexMovable() const +{ + const int items = Movable::counter.loadAcquire(); + { + QFETCH(QList, vector); + QFETCH(int, size); + + const int oldSize = vector.size(); + + vector.resize(size); + QCOMPARE(vector.size(), size); + QVERIFY(vector.capacity() >= size); + for (int i = oldSize; i < size; ++i) + QVERIFY(vector[i] == 'j'); // check initialization + + const int capacity = vector.capacity(); + + vector.resize(0); + QCOMPARE(vector.size(), 0); + QVERIFY(vector.capacity() <= capacity); + } + QCOMPARE(items, Movable::counter.loadAcquire()); +} + +void tst_QList::resizeComplex_data() const +{ + QTest::addColumn >("vector"); + QTest::addColumn("size"); + + QVERIFY(QTypeInfo::isComplex); + QVERIFY(QTypeInfo::isStatic); + + QList null; + QList empty(0, '0'); + QList emptyReserved; + QList nonEmpty; + QList nonEmptyReserved; + + emptyReserved.reserve(10); + nonEmptyReserved.reserve(15); + nonEmpty << '0' << '1' << '2' << '3' << '4'; + nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; + QVERIFY(emptyReserved.capacity() >= 10); + QVERIFY(nonEmptyReserved.capacity() >= 15); + + QTest::newRow("null") << null << 10; + QTest::newRow("empty") << empty << 10; + QTest::newRow("emptyReserved") << emptyReserved << 10; + QTest::newRow("nonEmpty") << nonEmpty << 10; + QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; +} + +void tst_QList::resizeComplex() const +{ + const int items = Custom::counter.loadAcquire(); + { + QFETCH(QList, vector); + QFETCH(int, size); + + int oldSize = vector.size(); + vector.resize(size); + QCOMPARE(vector.size(), size); + QVERIFY(vector.capacity() >= size); + for (int i = oldSize; i < size; ++i) + QVERIFY(vector[i].i == 'j'); // check default initialization + + const int capacity = vector.capacity(); + + vector.resize(0); + QCOMPARE(vector.size(), 0); + QVERIFY(vector.isEmpty()); + QVERIFY(vector.capacity() <= capacity); + } + QCOMPARE(Custom::counter.loadAcquire(), items); +} + +void tst_QList::resizeCtorAndDtor() const +{ + const int items = Custom::counter.loadAcquire(); + { + QList null; + QList empty(0, '0'); + QList emptyReserved; + QList nonEmpty; + QList nonEmptyReserved; + + emptyReserved.reserve(10); + nonEmptyReserved.reserve(15); + nonEmpty << '0' << '1' << '2' << '3' << '4'; + nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; + QVERIFY(emptyReserved.capacity() >= 10); + QVERIFY(nonEmptyReserved.capacity() >= 15); + + // start playing with vectors + null.resize(21); + nonEmpty.resize(2); + emptyReserved.resize(0); + nonEmpty.resize(0); + nonEmptyReserved.resize(2); + } + QCOMPARE(Custom::counter.loadAcquire(), items); +} + +void tst_QList::reverseIterators() const +{ + QList v; + v << 1 << 2 << 3 << 4; + QList vr = v; + std::reverse(vr.begin(), vr.end()); + const QList &cvr = vr; + QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); + QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); + QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); + QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); + QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); + QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); +} + +template +void tst_QList::size() const +{ + // zero size + QList myvec; + QVERIFY(myvec.size() == 0); + + // grow + myvec.append(SimpleValue::at(0)); + QVERIFY(myvec.size() == 1); + myvec.append(SimpleValue::at(1)); + QVERIFY(myvec.size() == 2); + + // shrink + myvec.remove(0); + QVERIFY(myvec.size() == 1); + myvec.remove(0); + QVERIFY(myvec.size() == 0); +} + +void tst_QList::sizeInt() const +{ + size(); +} + +void tst_QList::sizeMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + size(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::sizeCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + size(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +// ::squeeze() is tested in ::capacity(). + +void tst_QList::startsWith() const +{ + QList myvec; + + // empty vector + QVERIFY(!myvec.startsWith(1)); + + // add the one, should work + myvec.prepend(1); + QVERIFY(myvec.startsWith(1)); + + // add something else, fails now + myvec.prepend(3); + QVERIFY(!myvec.startsWith(1)); + + // remove it again :) + myvec.remove(0); + QVERIFY(myvec.startsWith(1)); +} + +template +void tst_QList::swap() const +{ + QList v1, v2; + T val1 = SimpleValue::at(0); + T val2 = SimpleValue::at(1); + T val3 = SimpleValue::at(2); + T val4 = SimpleValue::at(3); + T val5 = SimpleValue::at(4); + T val6 = SimpleValue::at(5); + v1 << val1 << val2 << val3; + v2 << val4 << val5 << val6; + + v1.swap(v2); + QCOMPARE(v1,QList() << val4 << val5 << val6); + QCOMPARE(v2,QList() << val1 << val2 << val3); +} + +void tst_QList::swapInt() const +{ + swap(); +} + +void tst_QList::swapMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + swap(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::swapCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + swap(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::toList() const +{ + QList myvec; + myvec << "A" << "B" << "C"; + + // make sure it converts and doesn't modify the original vector + QCOMPARE(myvec.toList(), QList() << "A" << "B" << "C"); + QCOMPARE(myvec, QList() << "A" << "B" << "C"); +} + +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +void tst_QList::toStdVector() const +{ + QList myvec; + myvec << "A" << "B" << "C"; + + std::vector svec = myvec.toStdVector(); + QCOMPARE(svec.at(0), QLatin1String("A")); + QCOMPARE(svec.at(1), QLatin1String("B")); + QCOMPARE(svec.at(2), QLatin1String("C")); + + QCOMPARE(myvec, QList() << "A" << "B" << "C"); +} +#endif + +void tst_QList::value() const +{ + QList myvec; + myvec << "A" << "B" << "C"; + + // valid calls + QCOMPARE(myvec.value(0), QLatin1String("A")); + QCOMPARE(myvec.value(1), QLatin1String("B")); + QCOMPARE(myvec.value(2), QLatin1String("C")); + + // default calls + QCOMPARE(myvec.value(-1), QString()); + QCOMPARE(myvec.value(3), QString()); + + // test calls with a provided default, valid calls + QCOMPARE(myvec.value(0, QLatin1String("default")), QLatin1String("A")); + QCOMPARE(myvec.value(1, QLatin1String("default")), QLatin1String("B")); + QCOMPARE(myvec.value(2, QLatin1String("default")), QLatin1String("C")); + + // test calls with a provided default that will return the default + QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default")); + QCOMPARE(myvec.value(3, QLatin1String("default")), QLatin1String("default")); +} + +void tst_QList::testOperators() const +{ + QList myvec; + myvec << "A" << "B" << "C"; + QList myvectwo; + myvectwo << "D" << "E" << "F"; + QList combined; + combined << "A" << "B" << "C" << "D" << "E" << "F"; + + // != + QVERIFY(myvec != myvectwo); + + // + + QCOMPARE(myvec + myvectwo, combined); + QCOMPARE(myvec, QList() << "A" << "B" << "C"); + QCOMPARE(myvectwo, QList() << "D" << "E" << "F"); + + // += + myvec += myvectwo; + QCOMPARE(myvec, combined); + + // == + QVERIFY(myvec == combined); + + // <, >, <=, >= + QVERIFY(!(myvec < combined)); + QVERIFY(!(myvec > combined)); + QVERIFY( myvec <= combined); + QVERIFY( myvec >= combined); + combined.push_back("G"); + QVERIFY( myvec < combined); + QVERIFY(!(myvec > combined)); + QVERIFY( myvec <= combined); + QVERIFY(!(myvec >= combined)); + QVERIFY(combined > myvec); + QVERIFY(combined >= myvec); + + // [] + QCOMPARE(myvec[0], QLatin1String("A")); + QCOMPARE(myvec[1], QLatin1String("B")); + QCOMPARE(myvec[2], QLatin1String("C")); + QCOMPARE(myvec[3], QLatin1String("D")); + QCOMPARE(myvec[4], QLatin1String("E")); + QCOMPARE(myvec[5], QLatin1String("F")); +} + + +int fooCtor; +int fooDtor; + +struct Foo +{ + int *p; + + Foo() { p = new int; ++fooCtor; } + Foo(const Foo &other) { Q_UNUSED(other); p = new int; ++fooCtor; } + + void operator=(const Foo & /* other */) { } + + ~Foo() { delete p; ++fooDtor; } +}; + +void tst_QList::reserve() +{ + fooCtor = 0; + fooDtor = 0; + { + QList a; + a.resize(2); + QCOMPARE(fooCtor, 2); + QList b(a); + b.reserve(1); + QCOMPARE(b.size(), a.size()); + QCOMPARE(fooDtor, 0); + } + QCOMPARE(fooCtor, fooDtor); +} + +// This is a regression test for QTBUG-51758 +void tst_QList::reserveZero() +{ + QList vec; + vec.detach(); + vec.reserve(0); // should not crash + QCOMPARE(vec.size(), 0); + QCOMPARE(vec.capacity(), 0); + vec.squeeze(); + QCOMPARE(vec.size(), 0); + QCOMPARE(vec.capacity(), 0); + vec.reserve(-1); + QCOMPARE(vec.size(), 0); + QCOMPARE(vec.capacity(), 0); + vec.append(42); + QCOMPARE(vec.size(), 1); + QVERIFY(vec.capacity() >= 1); +} + +template +void tst_QList::initializeList() +{ + T val1(SimpleValue::at(1)); + T val2(SimpleValue::at(2)); + T val3(SimpleValue::at(3)); + T val4(SimpleValue::at(4)); + + QList v1 {val1, val2, val3}; + QCOMPARE(v1, QList() << val1 << val2 << val3); + QCOMPARE(v1, (QList {val1, val2, val3})); + + QList> v2{ v1, {val4}, QList(), {val1, val2, val3} }; + QList> v3; + v3 << v1 << (QList() << val4) << QList() << v1; + QCOMPARE(v3, v2); + + QList v4({}); + QCOMPARE(v4.size(), 0); +} + +void tst_QList::initializeListInt() +{ + initializeList(); +} + +void tst_QList::initializeListMovable() +{ + const int instancesCount = Movable::counter.loadAcquire(); + initializeList(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::initializeListCustom() +{ + const int instancesCount = Custom::counter.loadAcquire(); + initializeList(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +void tst_QList::const_shared_null() +{ + QList v2; + QVERIFY(!v2.isDetached()); +} + +template +void tst_QList::detach() const +{ + { + // detach an empty vector + QList v; + v.detach(); + QVERIFY(!v.isDetached()); + QCOMPARE(v.size(), 0); + QCOMPARE(v.capacity(), 0); + } + { + // detach an empty referenced vector + QList v; + QList ref(v); + QVERIFY(!v.isDetached()); + v.detach(); + QVERIFY(!v.isDetached()); + QCOMPARE(v.size(), 0); + QCOMPARE(v.capacity(), 0); + } + { + // detach a not empty referenced vector + QList v(31); + QList ref(v); + QVERIFY(!v.isDetached()); + v.detach(); + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 31); + QCOMPARE(v.capacity(), 31); + } + { + // detach a not empty vector + QList v(31); + QVERIFY(v.isDetached()); + v.detach(); // detaching a detached vector + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 31); + QCOMPARE(v.capacity(), 31); + } + { + // detach a not empty vector with preallocated space + QList v(3); + v.reserve(8); + QList ref(v); + QVERIFY(!v.isDetached()); + v.detach(); + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 3); + QCOMPARE(v.capacity(), 8); + } + { + // detach a not empty vector with preallocated space + QList v(3); + v.reserve(8); + QVERIFY(v.isDetached()); + v.detach(); // detaching a detached vector + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 3); + QCOMPARE(v.capacity(), 8); + } + { + // detach a not empty, initialized vector + QList v(7, SimpleValue::at(1)); + QList ref(v); + QVERIFY(!v.isDetached()); + v.detach(); + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 7); + for (int i = 0; i < v.size(); ++i) + QCOMPARE(v[i], SimpleValue::at(1)); + } + { + // detach a not empty, initialized vector + QList v(7, SimpleValue::at(2)); + QVERIFY(v.isDetached()); + v.detach(); // detaching a detached vector + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 7); + for (int i = 0; i < v.size(); ++i) + QCOMPARE(v[i], SimpleValue::at(2)); + } + { + // detach a not empty, initialized vector with preallocated space + QList v(7, SimpleValue::at(3)); + v.reserve(31); + QList ref(v); + QVERIFY(!v.isDetached()); + v.detach(); + QVERIFY(v.isDetached()); + QCOMPARE(v.size(), 7); + QCOMPARE(v.capacity(), 31); + for (int i = 0; i < v.size(); ++i) + QCOMPARE(v[i], SimpleValue::at(3)); + } +} + +void tst_QList::detachInt() const +{ + detach(); +} + +void tst_QList::detachMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + detach(); + QCOMPARE(instancesCount, Movable::counter.loadAcquire()); +} + +void tst_QList::detachCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + detach(); + QCOMPARE(instancesCount, Custom::counter.loadAcquire()); +} + +static QAtomicPointer > detachThreadSafetyDataInt; +static QAtomicPointer > detachThreadSafetyDataMovable; +static QAtomicPointer > detachThreadSafetyDataCustom; + +template QAtomicPointer > *detachThreadSafetyData(); +template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; } +template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; } +template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; } + +static QSemaphore detachThreadSafetyLock; + +template +void tst_QList::detachThreadSafety() const +{ + delete detachThreadSafetyData()->fetchAndStoreOrdered(new QList(SimpleValue::vector(400))); + + static const uint threadsCount = 5; + + struct : QThread { + void run() override + { + QList copy(*detachThreadSafetyData()->loadRelaxed()); + QVERIFY(!copy.isDetached()); + detachThreadSafetyLock.release(); + detachThreadSafetyLock.acquire(100); + copy.detach(); + } + } threads[threadsCount]; + + for (uint i = 0; i < threadsCount; ++i) + threads[i].start(); + QThread::yieldCurrentThread(); + detachThreadSafetyLock.acquire(threadsCount); + + // destroy static original data + delete detachThreadSafetyData()->fetchAndStoreOrdered(0); + + QVERIFY(threadsCount < 100); + detachThreadSafetyLock.release(threadsCount * 100); + QThread::yieldCurrentThread(); + + for (uint i = 0; i < threadsCount; ++i) + threads[i].wait(); +} + +void tst_QList::detachThreadSafetyInt() const +{ + for (uint i = 0; i < 128; ++i) + detachThreadSafety(); +} + +void tst_QList::detachThreadSafetyMovable() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + for (uint i = 0; i < 128; ++i) { + detachThreadSafety(); + QCOMPARE(Movable::counter.loadAcquire(), instancesCount); + } +} + +void tst_QList::detachThreadSafetyCustom() const +{ + const int instancesCount = Custom::counter.loadAcquire(); + for (uint i = 0; i < 128; ++i) { + detachThreadSafety(); + QCOMPARE(Custom::counter.loadAcquire(), instancesCount); + } +} + +void tst_QList::insertMove() const +{ + const int instancesCount = Movable::counter.loadAcquire(); + { + QList vec; + vec.reserve(7); + Movable m0; + Movable m1; + Movable m2; + Movable m3; + Movable m4; + Movable m5; + Movable m6; + + vec.append(std::move(m3)); + QVERIFY(m3.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m3)); + vec.push_back(std::move(m4)); + QVERIFY(m4.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m3)); + QVERIFY(vec.at(1).wasConstructedAt(&m4)); + vec.prepend(std::move(m1)); + QVERIFY(m1.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m3)); + QVERIFY(vec.at(2).wasConstructedAt(&m4)); + vec.insert(1, std::move(m2)); + QVERIFY(m2.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + vec += std::move(m5); + QVERIFY(m5.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + vec << std::move(m6); + QVERIFY(m6.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + QVERIFY(vec.at(5).wasConstructedAt(&m6)); + vec.push_front(std::move(m0)); + QVERIFY(m0.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m0)); + QVERIFY(vec.at(1).wasConstructedAt(&m1)); + QVERIFY(vec.at(2).wasConstructedAt(&m2)); + QVERIFY(vec.at(3).wasConstructedAt(&m3)); + QVERIFY(vec.at(4).wasConstructedAt(&m4)); + QVERIFY(vec.at(5).wasConstructedAt(&m5)); + QVERIFY(vec.at(6).wasConstructedAt(&m6)); + + QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14); + } + QCOMPARE(Movable::counter.loadAcquire(), instancesCount); +} + +void tst_QList::swapItemsAt() const +{ + QList v; + v << 0 << 1 << 2 << 3; + + v.swapItemsAt(0, 2); + QCOMPARE(v.at(0), 2); + QCOMPARE(v.at(2), 0); + + auto copy = v; + copy.swapItemsAt(0, 2); + QCOMPARE(v.at(0), 2); + QCOMPARE(v.at(2), 0); + QCOMPARE(copy.at(0), 0); + QCOMPARE(copy.at(2), 2); +} + +void tst_QList::emplaceInt() +{ + emplaceImpl(); +} + +void tst_QList::emplaceCustom() +{ + emplaceImpl(); +} + +void tst_QList::emplaceMovable() +{ + emplaceImpl(); +} + +void tst_QList::emplaceConsistentWithStdVectorInt() +{ + emplaceConsistentWithStdVectorImpl(); +} + +void tst_QList::emplaceConsistentWithStdVectorCustom() +{ + emplaceConsistentWithStdVectorImpl(); +} + +void tst_QList::emplaceConsistentWithStdVectorMovable() +{ + emplaceConsistentWithStdVectorImpl(); +} + +void tst_QList::emplaceReturnsIterator() +{ + QList vec; + + vec.emplace(0, 'k')->i = 'p'; + + QCOMPARE(vec[0].i, 'p'); +} + +void tst_QList::emplaceBack() +{ + QScopedValueRollback rollback(Movable::counter, 0); + + QList vec; + + vec.emplaceBack('k'); + + QCOMPARE(Movable::counter, 1); +} + +void tst_QList::emplaceBackReturnsRef() +{ + QList vec; + + vec.emplaceBack('k').i = 'p'; + + QCOMPARE(vec.at(0).i, 'p'); +} + +void tst_QList::emplaceWithElementFromTheSameContainer() +{ + QFETCH(int, elementPos); + QFETCH(int, insertPos); + QFETCH(bool, doCopy); + + QList vec {"a", "b", "c", "d", "e"}; + const QString e = vec[elementPos]; + + if (doCopy) + vec.emplace(insertPos, vec[elementPos]); + else + vec.emplace(insertPos, std::move(vec[elementPos])); + + QCOMPARE(vec[insertPos], e); +} + +void tst_QList::emplaceWithElementFromTheSameContainer_data() +{ + QTest::addColumn("elementPos"); + QTest::addColumn("insertPos"); + QTest::addColumn("doCopy"); + + for (int i = 0; i < 2; ++i) { + const bool doCopy = i == 0; + const char *opName = doCopy ? "copy" : "move"; + + QTest::addRow("%s: begin -> end" , opName) << 0 << 5 << doCopy; + QTest::addRow("%s: begin -> middle", opName) << 0 << 2 << doCopy; + QTest::addRow("%s: middle -> begin" , opName) << 2 << 0 << doCopy; + QTest::addRow("%s: middle -> end" , opName) << 2 << 5 << doCopy; + QTest::addRow("%s: end -> middle", opName) << 4 << 2 << doCopy; + QTest::addRow("%s: end -> begin" , opName) << 4 << 0 << doCopy; + } +} + +template +void tst_QList::emplaceImpl() const +{ + QList vec {'a', 'b', 'c', 'd'}; + + vec.emplace(2, 'k'); + + QCOMPARE(vec[2], T('k')); +} + +template +static void vecEq(const QList &qVec, const std::vector &stdVec) +{ + QCOMPARE(std::size_t(qVec.size()), stdVec.size()); + QVERIFY(std::equal(qVec.begin(), qVec.end(), stdVec.begin(), stdVec.end())); +} + +template +static void squeezeVec(QList &qVec, std::vector &stdVec) +{ + qVec.squeeze(); + stdVec.shrink_to_fit(); +} + +template +void tst_QList::emplaceConsistentWithStdVectorImpl() const +{ + QList qVec {'a', 'b', 'c', 'd', 'e'}; + std::vector stdVec {'a', 'b', 'c', 'd', 'e'}; + vecEq(qVec, stdVec); + + qVec.emplaceBack('f'); + stdVec.emplace_back('f'); + vecEq(qVec, stdVec); + + qVec.emplace(3, 'g'); + stdVec.emplace(stdVec.begin() + 3, 'g'); + vecEq(qVec, stdVec); + + T t; + // while QVector is safe with regards to emplacing elements moved form itself, it's UB + // for std::vector, so do the moving in two steps there. + qVec.emplaceBack(std::move(qVec[0])); + stdVec.emplace_back(std::move(t = std::move(stdVec[0]))); + vecEq(qVec, stdVec); + + squeezeVec(qVec, stdVec); + + qVec.emplaceBack(std::move(qVec[1])); + stdVec.emplace_back(std::move(t = std::move(stdVec[1]))); + vecEq(qVec, stdVec); + + squeezeVec(qVec, stdVec); + + qVec.emplace(3, std::move(qVec[5])); + stdVec.emplace(stdVec.begin() + 3, std::move(t = std::move(stdVec[5]))); + + vecEq(qVec, stdVec); + + qVec.emplaceBack(qVec[3]); + stdVec.emplace_back((t = stdVec[3])); + vecEq(qVec, stdVec); + + squeezeVec(qVec, stdVec); + + qVec.emplaceBack(qVec[4]); + stdVec.emplace_back((t = stdVec[4])); + vecEq(qVec, stdVec); + + squeezeVec(qVec, stdVec); + + qVec.emplace(5, qVec[7]); + stdVec.emplace(stdVec.begin() + 5, (t = stdVec[7])); + vecEq(qVec, stdVec); +} + +QTEST_MAIN(tst_QList) +#include "tst_qlist.moc" diff --git a/tests/auto/corelib/tools/qvector/.gitignore b/tests/auto/corelib/tools/qvector/.gitignore deleted file mode 100644 index 5520039486..0000000000 --- a/tests/auto/corelib/tools/qvector/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qvector diff --git a/tests/auto/corelib/tools/qvector/CMakeLists.txt b/tests/auto/corelib/tools/qvector/CMakeLists.txt deleted file mode 100644 index d180a1be8c..0000000000 --- a/tests/auto/corelib/tools/qvector/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qvector.pro. - -##################################################################### -## tst_qvector Test: -##################################################################### - -qt_add_test(tst_qvector - SOURCES - tst_qvector.cpp -) - -## Scopes: -##################################################################### diff --git a/tests/auto/corelib/tools/qvector/qvector.pro b/tests/auto/corelib/tools/qvector/qvector.pro deleted file mode 100644 index 689d9b87a2..0000000000 --- a/tests/auto/corelib/tools/qvector/qvector.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -qtConfig(c++11): CONFIG += c++11 -qtConfig(c++14): CONFIG += c++14 -qtConfig(c++1z): CONFIG += c++1z -TARGET = tst_qvector -QT = core testlib -SOURCES = $$PWD/tst_qvector.cpp diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp deleted file mode 100644 index 899156545d..0000000000 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ /dev/null @@ -1,2834 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include - -struct Movable { - Movable(char input = 'j') - : i(input) - , that(this) - , state(Constructed) - { - counter.fetchAndAddRelaxed(1); - } - Movable(const Movable &other) - : i(other.i) - , that(this) - , state(Constructed) - { - check(other.state, Constructed); - counter.fetchAndAddRelaxed(1); - } - Movable(Movable &&other) - : i(other.i) - , that(other.that) - , state(Constructed) - { - check(other.state, Constructed); - counter.fetchAndAddRelaxed(1); - other.that = nullptr; - } - - ~Movable() - { - check(state, Constructed); - i = 0; - counter.fetchAndAddRelaxed(-1); - state = Destructed; - } - - bool operator ==(const Movable &other) const - { - check(state, Constructed); - check(other.state, Constructed); - return i == other.i; - } - - Movable &operator=(const Movable &other) - { - check(state, Constructed); - check(other.state, Constructed); - i = other.i; - that = this; - return *this; - } - Movable &operator=(Movable &&other) - { - check(state, Constructed); - check(other.state, Constructed); - i = other.i; - that = other.that; - other.that = nullptr; - return *this; - } - bool wasConstructedAt(const Movable *other) const - { - return that == other; - } - char i; - static QAtomicInt counter; -private: - Movable *that; // used to check if an instance was moved - - enum State { Constructed = 106, Destructed = 110 }; - State state; - - static void check(const State state1, const State state2) - { - QCOMPARE(int(state1), int(state2)); - } -}; - -inline size_t qHash(const Movable &key, size_t seed = 0) { return qHash(key.i, seed); } - -QAtomicInt Movable::counter = 0; -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); -QT_END_NAMESPACE -Q_DECLARE_METATYPE(Movable); - -struct Custom { - Custom(char input = 'j') - : i(input) - , that(this) - , state(Constructed) - { - counter.fetchAndAddRelaxed(1); - } - Custom(const Custom &other) - : that(this) - , state(Constructed) - { - check(&other); - counter.fetchAndAddRelaxed(1); - this->i = other.i; - } - ~Custom() - { - check(this); - i = 0; - counter.fetchAndAddRelaxed(-1); - state = Destructed; - } - - bool operator ==(const Custom &other) const - { - check(&other); - check(this); - return i == other.i; - } - - bool operator<(const Custom &other) const - { - check(&other); - check(this); - return i < other.i; - } - - Custom &operator=(const Custom &other) - { - check(&other); - check(this); - i = other.i; - return *this; - } - static QAtomicInt counter; - - char i; // used to identify orgin of an instance -private: - Custom *that; // used to check if an instance was moved - - enum State { Constructed = 106, Destructed = 110 }; - State state; - - static void check(const Custom *c) - { - // check if c object has been moved - QCOMPARE(c, c->that); - QCOMPARE(int(c->state), int(Constructed)); - } -}; -QAtomicInt Custom::counter = 0; - -inline size_t qHash(const Custom &key, size_t seed = 0) { return qHash(key.i, seed); } - -Q_DECLARE_METATYPE(Custom); - -// tests depends on the fact that: -static_assert(!QTypeInfo::isStatic); -static_assert(!QTypeInfo::isComplex); -static_assert(!QTypeInfo::isStatic); -static_assert(QTypeInfo::isComplex); -static_assert(QTypeInfo::isStatic); -static_assert(QTypeInfo::isComplex); - - -class tst_QVector : public QObject -{ - Q_OBJECT -private slots: - void constructors_empty() const; - void constructors_emptyReserveZero() const; - void constructors_emptyReserve() const; - void constructors_reserveAndInitialize() const; - void copyConstructorInt() const; - void copyConstructorMovable() const; - void copyConstructorCustom() const; - void assignmentInt() const; - void assignmentMovable() const; - void assignmentCustom() const; - void assignFromInitializerListInt() const; - void assignFromInitializerListMovable() const; - void assignFromInitializerListCustom() const; - void addInt() const; - void addMovable() const; - void addCustom() const; - void appendInt() const; - void appendMovable() const; - void appendCustom() const; - void appendRvalue() const; - void at() const; - void capacityInt() const; - void capacityMovable() const; - void capacityCustom() const; - void clearInt() const; - void clearMovable() const; - void clearCustom() const; - void constData() const; - void constFirst() const; - void constLast() const; - void contains() const; - void countInt() const; - void countMovable() const; - void countCustom() const; - void cpp17ctad() const; - void data() const; - void emptyInt() const; - void emptyMovable() const; - void emptyCustom() const; - void endsWith() const; - void eraseEmptyInt() const; - void eraseEmptyMovable() const; - void eraseEmptyCustom() const; - void eraseEmptyReservedInt() const; - void eraseEmptyReservedMovable() const; - void eraseEmptyReservedCustom() const; - void eraseInt() const; - void eraseIntShared() const; - void eraseMovable() const; - void eraseMovableShared() const; - void eraseCustom() const; - void eraseCustomShared() const; - void eraseReservedInt() const; - void eraseReservedMovable() const; - void eraseReservedCustom() const; - void fillInt() const; - void fillMovable() const; - void fillCustom() const; - void fillDetaches() const; - void first() const; - void fromListInt() const; - void fromListMovable() const; - void fromListCustom() const; - void indexOf() const; - void insertInt() const; - void insertMovable() const; - void insertCustom() const; - void isEmpty() const; - void last() const; - void lastIndexOf() const; - void mid() const; - void moveInt() const; - void moveMovable() const; - void moveCustom() const; - void prependInt() const; - void prependMovable() const; - void prependCustom() const; - void qhashInt() const { qhash(); } - void qhashMovable() const { qhash(); } - void qhashCustom() const { qhash(); } - void removeAllWithAlias() const; - void removeInt() const; - void removeMovable() const; - void removeCustom() const; - void removeFirstLast() const; - void resizePOD_data() const; - void resizePOD() const; - void resizeComplexMovable_data() const; - void resizeComplexMovable() const; - void resizeComplex_data() const; - void resizeComplex() const; - void resizeCtorAndDtor() const; - void reverseIterators() const; - void sizeInt() const; - void sizeMovable() const; - void sizeCustom() const; - void startsWith() const; - void swapInt() const; - void swapMovable() const; - void swapCustom() const; - void toList() const; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - void fromStdVector() const; - void toStdVector() const; -#endif - void value() const; - - void testOperators() const; - - void reserve(); - void reserveZero(); - void initializeListInt(); - void initializeListMovable(); - void initializeListCustom(); - - void const_shared_null(); - - void detachInt() const; - void detachMovable() const; - void detachCustom() const; - void detachThreadSafetyInt() const; - void detachThreadSafetyMovable() const; - void detachThreadSafetyCustom() const; - - void insertMove() const; - - void swapItemsAt() const; - - void emplaceInt(); - void emplaceCustom(); - void emplaceMovable(); - void emplaceConsistentWithStdVectorInt(); - void emplaceConsistentWithStdVectorCustom(); - void emplaceConsistentWithStdVectorMovable(); - void emplaceReturnsIterator(); - void emplaceBack(); - void emplaceBackReturnsRef(); - void emplaceWithElementFromTheSameContainer(); - void emplaceWithElementFromTheSameContainer_data(); - -private: - template void copyConstructor() const; - template void add() const; - template void append() const; - template void assignFromInitializerList() const; - template void capacity() const; - template void clear() const; - template void count() const; - template void empty() const; - template void eraseEmpty() const; - template void eraseEmptyReserved() const; - template void erase(bool shared) const; - template void eraseReserved() const; - template void fill() const; - template void fromList() const; - template void insert() const; - template void qhash() const; - template void move() const; - template void prepend() const; - template void remove() const; - template void size() const; - template void swap() const; - template void initializeList(); - template void detach() const; - template void detachThreadSafety() const; - template void emplaceImpl() const; - template void emplaceConsistentWithStdVectorImpl() const; -}; - - -template struct SimpleValue -{ - static T at(int index) - { - return Values[index % MaxIndex]; - } - - static QVector vector(int size) - { - QVector ret; - for (int i = 0; i < size; i++) - ret.append(at(i)); - return ret; - } - - static const uint MaxIndex = 6; - static const T Values[MaxIndex]; -}; - -template<> -const int SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; -template<> -const Movable SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; -template<> -const Custom SimpleValue::Values[] = { 110, 105, 101, 114, 111, 98 }; - -// Make some macros for the tests to use in order to be slightly more readable... -#define T_FOO SimpleValue::at(0) -#define T_BAR SimpleValue::at(1) -#define T_BAZ SimpleValue::at(2) -#define T_CAT SimpleValue::at(3) -#define T_DOG SimpleValue::at(4) -#define T_BLAH SimpleValue::at(5) - -void tst_QVector::constructors_empty() const -{ - QVector emptyInt; - QVector emptyMovable; - QVector emptyCustom; -} - -void tst_QVector::constructors_emptyReserveZero() const -{ - QVector emptyInt(0); - QVector emptyMovable(0); - QVector emptyCustom(0); -} - -void tst_QVector::constructors_emptyReserve() const -{ - // pre-reserve capacity - QVector myInt(5); - QVERIFY(myInt.capacity() == 5); - QVector myMovable(5); - QVERIFY(myMovable.capacity() == 5); - QVector myCustom(4); - QVERIFY(myCustom.capacity() == 4); -} - -void tst_QVector::constructors_reserveAndInitialize() const -{ - // default-initialise items - - QVector myInt(5, 42); - QVERIFY(myInt.capacity() == 5); - foreach (int meaningoflife, myInt) { - QCOMPARE(meaningoflife, 42); - } - - QVector myString(5, QString::fromLatin1("c++")); - QVERIFY(myString.capacity() == 5); - // make sure all items are initialised ok - foreach (QString meaningoflife, myString) { - QCOMPARE(meaningoflife, QString::fromLatin1("c++")); - } - - QVector myCustom(5, Custom('n')); - QVERIFY(myCustom.capacity() == 5); - // make sure all items are initialised ok - foreach (Custom meaningoflife, myCustom) { - QCOMPARE(meaningoflife.i, 'n'); - } -} - -template -void tst_QVector::copyConstructor() const -{ - T value1(SimpleValue::at(0)); - T value2(SimpleValue::at(1)); - T value3(SimpleValue::at(2)); - T value4(SimpleValue::at(3)); - { - QVector v1; - QVector v2(v1); - QCOMPARE(v1, v2); - } - { - QVector v1; - v1 << value1 << value2 << value3 << value4; - QVector v2(v1); - QCOMPARE(v1, v2); - } -} - -void tst_QVector::copyConstructorInt() const -{ - copyConstructor(); -} - -void tst_QVector::copyConstructorMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - copyConstructor(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::copyConstructorCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - copyConstructor(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -static inline void testAssignment() -{ - QVector v1(5); - QCOMPARE(v1.size(), 5); - QVERIFY(v1.isDetached()); - - QVector v2(7); - QCOMPARE(v2.size(), 7); - QVERIFY(v2.isDetached()); - - QVERIFY(!v1.isSharedWith(v2)); - - v1 = v2; - - QVERIFY(!v1.isDetached()); - QVERIFY(!v2.isDetached()); - QVERIFY(v1.isSharedWith(v2)); - - const void *const data1 = v1.constData(); - const void *const data2 = v2.constData(); - - QCOMPARE(data1, data2); - - v1.clear(); - - QVERIFY(v2.isDetached()); - QVERIFY(!v1.isSharedWith(v2)); - QCOMPARE((void *)v2.constData(), data2); -} - -void tst_QVector::assignmentInt() const -{ - testAssignment(); -} - -void tst_QVector::assignmentMovable() const -{ - testAssignment(); -} - -void tst_QVector::assignmentCustom() const -{ - testAssignment(); -} - -template -void tst_QVector::assignFromInitializerList() const -{ - T val1(SimpleValue::at(1)); - T val2(SimpleValue::at(2)); - T val3(SimpleValue::at(3)); - - QVector v1 = {val1, val2, val3}; - QCOMPARE(v1, QVector() << val1 << val2 << val3); - QCOMPARE(v1, (QVector {val1, val2, val3})); - - v1 = {}; - QCOMPARE(v1.size(), 0); -} - -void tst_QVector::assignFromInitializerListInt() const -{ - assignFromInitializerList(); -} - -void tst_QVector::assignFromInitializerListMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - assignFromInitializerList(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::assignFromInitializerListCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - assignFromInitializerList(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::add() const -{ - { - QVector empty1; - QVector empty2; - QVERIFY((empty1 + empty2).isEmpty()); - empty1 += empty2; - QVERIFY(empty1.isEmpty()); - QVERIFY(empty2.isEmpty()); - } - { - QVector v(12); - QVector empty; - QCOMPARE((v + empty), v); - v += empty; - QVERIFY(!v.isEmpty()); - QCOMPARE(v.size(), 12); - QVERIFY(empty.isEmpty()); - } - { - QVector v1(12); - QVector v2; - v2 += v1; - QVERIFY(!v1.isEmpty()); - QCOMPARE(v1.size(), 12); - QVERIFY(!v2.isEmpty()); - QCOMPARE(v2.size(), 12); - } -} - -void tst_QVector::addInt() const -{ - add(); -} - -void tst_QVector::addMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - add(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::addCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - add(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::append() const -{ - { - QVector myvec; - myvec.append(SimpleValue::at(0)); - QVERIFY(myvec.size() == 1); - myvec.append(SimpleValue::at(1)); - QVERIFY(myvec.size() == 2); - myvec.append(SimpleValue::at(2)); - QVERIFY(myvec.size() == 3); - - QCOMPARE(myvec, QVector() << SimpleValue::at(0) - << SimpleValue::at(1) - << SimpleValue::at(2)); - } - { - QVector v(2); - v.append(SimpleValue::at(0)); - QVERIFY(v.size() == 3); - QCOMPARE(v.at(v.size() - 1), SimpleValue::at(0)); - } - { - QVector v(2); - v.reserve(12); - v.append(SimpleValue::at(0)); - QVERIFY(v.size() == 3); - QCOMPARE(v.at(v.size() - 1), SimpleValue::at(0)); - } - { - QVector v; - v << 1 << 2 << 3; - QVector x; - x << 4 << 5 << 6; - v.append(x); - - QVector combined; - combined << 1 << 2 << 3 << 4 << 5 << 6; - - QCOMPARE(v, combined); - } -} - -void tst_QVector::appendInt() const -{ - append(); -} - -void tst_QVector::appendMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - append(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::appendCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - append(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::appendRvalue() const -{ - QVector v; - v.append("hello"); - QString world = "world"; - v.append(std::move(world)); - QVERIFY(world.isEmpty()); - QCOMPARE(v.front(), QString("hello")); - QCOMPARE(v.back(), QString("world")); -} - -void tst_QVector::at() const -{ - QVector myvec; - myvec << "foo" << "bar" << "baz"; - - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("bar")); - QCOMPARE(myvec.at(2), QLatin1String("baz")); - - // append an item - myvec << "hello"; - QVERIFY(myvec.size() == 4); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("bar")); - QCOMPARE(myvec.at(2), QLatin1String("baz")); - QCOMPARE(myvec.at(3), QLatin1String("hello")); - - // remove an item - myvec.remove(1); - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), QLatin1String("foo")); - QCOMPARE(myvec.at(1), QLatin1String("baz")); - QCOMPARE(myvec.at(2), QLatin1String("hello")); -} - -template -void tst_QVector::capacity() const -{ - QVector myvec; - - // TODO: is this guaranteed? seems a safe assumption, but I suppose preallocation of a - // few items isn't an entirely unforseeable possibility. - QVERIFY(myvec.capacity() == 0); - - // test it gets a size - myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); - QVERIFY(myvec.capacity() >= 3); - - // make sure it grows ok - myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); - QVERIFY(myvec.capacity() >= 6); - // let's try squeeze a bit - myvec.remove(3); - myvec.remove(3); - myvec.remove(3); - myvec.squeeze(); - QVERIFY(myvec.capacity() >= 3); - - myvec.remove(0); - myvec.remove(0); - myvec.remove(0); - myvec.squeeze(); - QVERIFY(myvec.capacity() == 0); -} - -void tst_QVector::capacityInt() const -{ - capacity(); -} - -void tst_QVector::capacityMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - capacity(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::capacityCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - capacity(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::clear() const -{ - QVector myvec; - myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); - - const auto oldCapacity = myvec.capacity(); - QCOMPARE(myvec.size(), 3); - myvec.clear(); - QCOMPARE(myvec.size(), 0); - QCOMPARE(myvec.capacity(), oldCapacity); -} - -void tst_QVector::clearInt() const -{ - clear(); -} - -void tst_QVector::clearMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - clear(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::clearCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - clear(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::constData() const -{ - int arr[] = { 42, 43, 44 }; - QVector myvec; - myvec << 42 << 43 << 44; - - QVERIFY(memcmp(myvec.constData(), reinterpret_cast(&arr), sizeof(int) * 3) == 0); -} - -void tst_QVector::contains() const -{ - QVector myvec; - myvec << "aaa" << "bbb" << "ccc"; - - QVERIFY(myvec.contains(QLatin1String("aaa"))); - QVERIFY(myvec.contains(QLatin1String("bbb"))); - QVERIFY(myvec.contains(QLatin1String("ccc"))); - QVERIFY(!myvec.contains(QLatin1String("I don't exist"))); - - // add it and make sure it does :) - myvec.append(QLatin1String("I don't exist")); - QVERIFY(myvec.contains(QLatin1String("I don't exist"))); -} - -template -void tst_QVector::count() const -{ - // total size - { - // zero size - QVector myvec; - QVERIFY(myvec.count() == 0); - - // grow - myvec.append(SimpleValue::at(0)); - QVERIFY(myvec.count() == 1); - myvec.append(SimpleValue::at(1)); - QVERIFY(myvec.count() == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.count() == 1); - myvec.remove(0); - QVERIFY(myvec.count() == 0); - } - - // count of items - { - QVector myvec; - myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); - - // initial tests - QVERIFY(myvec.count(SimpleValue::at(0)) == 1); - QVERIFY(myvec.count(SimpleValue::at(3)) == 0); - - // grow - myvec.append(SimpleValue::at(0)); - QVERIFY(myvec.count(SimpleValue::at(0)) == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.count(SimpleValue::at(0)) == 1); - } -} - -void tst_QVector::countInt() const -{ - count(); -} - -void tst_QVector::countMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - count(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::countCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - count(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::cpp17ctad() const -{ -#ifdef __cpp_deduction_guides -#define QVERIFY_IS_VECTOR_OF(obj, Type) \ - QVERIFY2((std::is_same>::value), \ - QMetaType::typeName(qMetaTypeId())) -#define CHECK(Type, One, Two, Three) \ - do { \ - const Type v[] = {One, Two, Three}; \ - QVector v1 = {One, Two, Three}; \ - QVERIFY_IS_VECTOR_OF(v1, Type); \ - QVector v2(v1.begin(), v1.end()); \ - QVERIFY_IS_VECTOR_OF(v2, Type); \ - QVector v3(std::begin(v), std::end(v)); \ - QVERIFY_IS_VECTOR_OF(v3, Type); \ - } while (false) \ - /*end*/ - CHECK(int, 1, 2, 3); - CHECK(double, 1.0, 2.0, 3.0); - CHECK(QString, QStringLiteral("one"), QStringLiteral("two"), QStringLiteral("three")); -#undef QVERIFY_IS_VECTOR_OF -#undef CHECK -#else - QSKIP("This test requires C++17 Constructor Template Argument Deduction support enabled in the compiler."); -#endif -} - -void tst_QVector::data() const -{ - QVector myvec; - myvec << 42 << 43 << 44; - - // make sure it starts off ok - QCOMPARE(*(myvec.data() + 1), 43); - - // alter it - *(myvec.data() + 1) = 69; - - // check it altered - QCOMPARE(*(myvec.data() + 1), 69); - - int arr[] = { 42, 69, 44 }; - QVERIFY(memcmp(myvec.data(), reinterpret_cast(&arr), sizeof(int) * 3) == 0); -} - -template -void tst_QVector::empty() const -{ - QVector myvec; - - // starts empty - QVERIFY(myvec.empty()); - - // not empty - myvec.append(SimpleValue::at(2)); - QVERIFY(!myvec.empty()); - - // empty again - myvec.remove(0); - QVERIFY(myvec.empty()); -} - -void tst_QVector::emptyInt() const -{ - empty(); -} - -void tst_QVector::emptyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - empty(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::emptyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - empty(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::endsWith() const -{ - QVector myvec; - - // empty vector - QVERIFY(!myvec.endsWith(1)); - - // add the one, should work - myvec.append(1); - QVERIFY(myvec.endsWith(1)); - - // add something else, fails now - myvec.append(3); - QVERIFY(!myvec.endsWith(1)); - - // remove it again :) - myvec.remove(1); - QVERIFY(myvec.endsWith(1)); -} - -template -void tst_QVector::eraseEmpty() const -{ - QVector v; - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); -} - -void tst_QVector::eraseEmptyInt() const -{ - eraseEmpty(); -} - -void tst_QVector::eraseEmptyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseEmpty(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseEmptyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseEmpty(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::eraseEmptyReserved() const -{ - QVector v; - v.reserve(10); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); -} - -void tst_QVector::eraseEmptyReservedInt() const -{ - eraseEmptyReserved(); -} - -void tst_QVector::eraseEmptyReservedMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseEmptyReserved(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseEmptyReservedCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseEmptyReserved(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -struct SharedVectorChecker -{ - SharedVectorChecker(const QVector &original, bool doCopyVector) - : originalSize(-1), - copy(0) - { - if (doCopyVector) { - originalSize = original.size(); - copy = new QVector(original); - // this is unlikely to fail, but if the check in the destructor fails it's good to know that - // we were still alright here. - QCOMPARE(originalSize, copy->size()); - } - } - - ~SharedVectorChecker() - { - if (copy) - QCOMPARE(copy->size(), originalSize); - delete copy; - } - - int originalSize; - QVector *copy; -}; - -template -void tst_QVector::erase(bool shared) const -{ - // note: remove() is actually more efficient, and more dangerous, because it uses the non-detaching - // begin() / end() internally. you can also use constBegin() and constEnd() with erase(), but only - // using reinterpret_cast... because both iterator types are really just pointers. - // so we use a mix of erase() and remove() to cover more cases. - { - QVector v = SimpleValue::vector(12); - SharedVectorChecker svc(v, shared); - v.erase(v.begin()); - QCOMPARE(v.size(), 11); - for (int i = 0; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue::at(i + 1)); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); - if (shared) - QCOMPARE(SimpleValue::vector(12), *svc.copy); - } - { - QVector v = SimpleValue::vector(12); - SharedVectorChecker svc(v, shared); - v.remove(1); - QCOMPARE(v.size(), 11); - QCOMPARE(v.at(0), SimpleValue::at(0)); - for (int i = 1; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue::at(i + 1)); - v.erase(v.begin() + 1, v.end()); - QCOMPARE(v.size(), 1); - QCOMPARE(v.at(0), SimpleValue::at(0)); - if (shared) - QCOMPARE(SimpleValue::vector(12), *svc.copy); - } - { - QVector v = SimpleValue::vector(12); - SharedVectorChecker svc(v, shared); - v.erase(v.begin(), v.end() - 1); - QCOMPARE(v.size(), 1); - QCOMPARE(v.at(0), SimpleValue::at(11)); - if (shared) - QCOMPARE(SimpleValue::vector(12), *svc.copy); - } - { - QVector v = SimpleValue::vector(12); - SharedVectorChecker svc(v, shared); - v.remove(5); - QCOMPARE(v.size(), 11); - for (int i = 0; i < 5; i++) - QCOMPARE(v.at(i), SimpleValue::at(i)); - for (int i = 5; i < 11; i++) - QCOMPARE(v.at(i), SimpleValue::at(i + 1)); - v.erase(v.begin() + 1, v.end() - 1); - QCOMPARE(v.at(0), SimpleValue::at(0)); - QCOMPARE(v.at(1), SimpleValue::at(11)); - QCOMPARE(v.size(), 2); - if (shared) - QCOMPARE(SimpleValue::vector(12), *svc.copy); - } -} - -void tst_QVector::eraseInt() const -{ - erase(false); -} - -void tst_QVector::eraseIntShared() const -{ - erase(true); -} - -void tst_QVector::eraseMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - erase(false); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseMovableShared() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - erase(true); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - erase(false); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::eraseCustomShared() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - erase(true); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template void tst_QVector::eraseReserved() const -{ - { - QVector v(12); - v.reserve(16); - v.erase(v.begin()); - QCOMPARE(v.size(), 11); - v.erase(v.begin(), v.end()); - QCOMPARE(v.size(), 0); - } - { - QVector v(12); - v.reserve(16); - v.erase(v.begin() + 1); - QCOMPARE(v.size(), 11); - v.erase(v.begin() + 1, v.end()); - QCOMPARE(v.size(), 1); - } - { - QVector v(12); - v.reserve(16); - v.erase(v.begin(), v.end() - 1); - QCOMPARE(v.size(), 1); - } - { - QVector v(12); - v.reserve(16); - v.erase(v.begin() + 5); - QCOMPARE(v.size(), 11); - v.erase(v.begin() + 1, v.end() - 1); - QCOMPARE(v.size(), 2); - } -} - -void tst_QVector::eraseReservedInt() const -{ - eraseReserved(); -} - -void tst_QVector::eraseReservedMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - eraseReserved(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::eraseReservedCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - eraseReserved(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::fill() const -{ - QVector myvec; - - // resize - myvec.resize(5); - myvec.fill(SimpleValue::at(1)); - QCOMPARE(myvec, QVector() << SimpleValue::at(1) << SimpleValue::at(1) - << SimpleValue::at(1) << SimpleValue::at(1) - << SimpleValue::at(1)); - - // make sure it can resize itself too - myvec.fill(SimpleValue::at(2), 10); - QCOMPARE(myvec, QVector() << SimpleValue::at(2) << SimpleValue::at(2) - << SimpleValue::at(2) << SimpleValue::at(2) - << SimpleValue::at(2) << SimpleValue::at(2) - << SimpleValue::at(2) << SimpleValue::at(2) - << SimpleValue::at(2) << SimpleValue::at(2)); -} - -void tst_QVector::fillInt() const -{ - fill(); -} - -void tst_QVector::fillMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - fill(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::fillCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - fill(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::fillDetaches() const -{ - QVector test = { 1, 2, 3 }; - QVector copy = test; - copy.fill(42); - - QCOMPARE(test, QVector({1, 2, 3})); - QCOMPARE(copy, QVector({42, 42, 42})); -} - -void tst_QVector::first() const -{ - QVector myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.first(), 69); - QCOMPARE(myvec.constFirst(), 69); - - // test removal changes - myvec.remove(0); - QCOMPARE(myvec.first(), 42); - QCOMPARE(myvec.constFirst(), 42); - - // test prepend changes - myvec.prepend(23); - QCOMPARE(myvec.first(), 23); - QCOMPARE(myvec.constFirst(), 23); -} - -void tst_QVector::constFirst() const -{ - QVector myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.constFirst(), 69); - QVERIFY(myvec.isDetached()); - - QVector myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 69); - QCOMPARE(myvecCopy.constFirst(), 69); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test removal changes - myvec.remove(0); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constFirst(), 42); - QCOMPARE(myvecCopy.constFirst(), 69); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 42); - QCOMPARE(myvecCopy.constFirst(), 42); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test prepend changes - myvec.prepend(23); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constFirst(), 23); - QCOMPARE(myvecCopy.constFirst(), 42); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constFirst(), 23); - QCOMPARE(myvecCopy.constFirst(), 23); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); -} - - -template -void tst_QVector::fromList() const -{ - QList list; - list << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3); - - QVector myvec; - myvec = QVector::fromList(list); - - // test it worked ok - QCOMPARE(myvec, QVector() << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3)); - QCOMPARE(list, QList() << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2) << SimpleValue::at(3)); -} - -void tst_QVector::fromListInt() const -{ - fromList(); -} - -void tst_QVector::fromListMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - fromList(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::fromListCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - fromList(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -void tst_QVector::fromStdVector() const -{ - // stl = :( - std::vector svec; - svec.push_back(QLatin1String("aaa")); - svec.push_back(QLatin1String("bbb")); - svec.push_back(QLatin1String("ninjas")); - svec.push_back(QLatin1String("pirates")); - QVector myvec = QVector::fromStdVector(svec); - - // test it converts ok - QCOMPARE(myvec, QVector() << "aaa" << "bbb" << "ninjas" << "pirates"); -} -#endif - -void tst_QVector::indexOf() const -{ - QVector myvec; - myvec << "A" << "B" << "C" << "B" << "A"; - - QVERIFY(myvec.indexOf("B") == 1); - QVERIFY(myvec.indexOf("B", 1) == 1); - QVERIFY(myvec.indexOf("B", 2) == 3); - QVERIFY(myvec.indexOf("X") == -1); - QVERIFY(myvec.indexOf("X", 2) == -1); - - // add an X - myvec << "X"; - QVERIFY(myvec.indexOf("X") == 5); - QVERIFY(myvec.indexOf("X", 5) == 5); - QVERIFY(myvec.indexOf("X", 6) == -1); - - // remove first A - myvec.remove(0); - QVERIFY(myvec.indexOf("A") == 3); - QVERIFY(myvec.indexOf("A", 3) == 3); - QVERIFY(myvec.indexOf("A", 4) == -1); -} - -template -void tst_QVector::insert() const -{ - QVector myvec; - const T - tA = SimpleValue::at(0), - tB = SimpleValue::at(1), - tC = SimpleValue::at(2), - tX = SimpleValue::at(3), - tZ = SimpleValue::at(4), - tT = SimpleValue::at(5), - ti = SimpleValue::at(6); - myvec << tA << tB << tC; - QVector myvec2 = myvec; - - // first position - QCOMPARE(myvec.at(0), tA); - myvec.insert(0, tX); - QCOMPARE(myvec.at(0), tX); - QCOMPARE(myvec.at(1), tA); - - QCOMPARE(myvec2.at(0), tA); - myvec2.insert(myvec2.begin(), tX); - QCOMPARE(myvec2.at(0), tX); - QCOMPARE(myvec2.at(1), tA); - - // middle - myvec.insert(1, tZ); - QCOMPARE(myvec.at(0), tX); - QCOMPARE(myvec.at(1), tZ); - QCOMPARE(myvec.at(2), tA); - - myvec2.insert(myvec2.begin() + 1, tZ); - QCOMPARE(myvec2.at(0), tX); - QCOMPARE(myvec2.at(1), tZ); - QCOMPARE(myvec2.at(2), tA); - - // end - myvec.insert(5, tT); - QCOMPARE(myvec.at(5), tT); - QCOMPARE(myvec.at(4), tC); - - myvec2.insert(myvec2.end(), tT); - QCOMPARE(myvec2.at(5), tT); - QCOMPARE(myvec2.at(4), tC); - - // insert a lot of garbage in the middle - myvec.insert(2, 2, ti); - QCOMPARE(myvec, QVector() << tX << tZ << ti << ti - << tA << tB << tC << tT); - - myvec2.insert(myvec2.begin() + 2, 2, ti); - QCOMPARE(myvec2, myvec); - - // insert from references to the same container: - myvec.insert(0, 1, myvec[5]); // inserts tB - myvec2.insert(0, 1, myvec2[5]); // inserts tB - QCOMPARE(myvec, QVector() << tB << tX << tZ << ti << ti - << tA << tB << tC << tT); - QCOMPARE(myvec2, myvec); - - myvec.insert(0, 1, const_cast&>(myvec)[0]); // inserts tB - myvec2.insert(0, 1, const_cast&>(myvec2)[0]); // inserts tB - QCOMPARE(myvec, QVector() << tB << tB << tX << tZ << ti << ti - << tA << tB << tC << tT); - QCOMPARE(myvec2, myvec); -} - -void tst_QVector::insertInt() const -{ - insert(); -} - -void tst_QVector::insertMovable() const -{ - insert(); -} - -void tst_QVector::insertCustom() const -{ - insert(); -} - -void tst_QVector::isEmpty() const -{ - QVector myvec; - - // starts ok - QVERIFY(myvec.isEmpty()); - - // not empty now - myvec.append(QLatin1String("hello there")); - QVERIFY(!myvec.isEmpty()); - - // empty again - myvec.remove(0); - QVERIFY(myvec.isEmpty()); -} - -void tst_QVector::last() const -{ - QVector myvec; - myvec << "A" << "B" << "C"; - - // test starts ok - QCOMPARE(myvec.last(), QLatin1String("C")); - QCOMPARE(myvec.constLast(), QLatin1String("C")); - - // test it changes ok - myvec.append(QLatin1String("X")); - QCOMPARE(myvec.last(), QLatin1String("X")); - QCOMPARE(myvec.constLast(), QLatin1String("X")); - - // and remove again - myvec.remove(3); - QCOMPARE(myvec.last(), QLatin1String("C")); - QCOMPARE(myvec.constLast(), QLatin1String("C")); -} - -void tst_QVector::constLast() const -{ - QVector myvec; - myvec << 69 << 42 << 3; - - // test it starts ok - QCOMPARE(myvec.constLast(), 3); - QVERIFY(myvec.isDetached()); - - QVector myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 3); - QCOMPARE(myvecCopy.constLast(), 3); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test removal changes - myvec.removeLast(); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constLast(), 42); - QCOMPARE(myvecCopy.constLast(), 3); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 42); - QCOMPARE(myvecCopy.constLast(), 42); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - // test prepend changes - myvec.append(23); - QVERIFY(myvec.isDetached()); - QVERIFY(!myvec.isSharedWith(myvecCopy)); - QCOMPARE(myvec.constLast(), 23); - QCOMPARE(myvecCopy.constLast(), 42); - - myvecCopy = myvec; - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); - - QCOMPARE(myvec.constLast(), 23); - QCOMPARE(myvecCopy.constLast(), 23); - - QVERIFY(!myvec.isDetached()); - QVERIFY(!myvecCopy.isDetached()); - QVERIFY(myvec.isSharedWith(myvecCopy)); - QVERIFY(myvecCopy.isSharedWith(myvec)); -} - -void tst_QVector::lastIndexOf() const -{ - QVector myvec; - myvec << "A" << "B" << "C" << "B" << "A"; - - QVERIFY(myvec.lastIndexOf("B") == 3); - QVERIFY(myvec.lastIndexOf("B", 2) == 1); - QVERIFY(myvec.lastIndexOf("X") == -1); - QVERIFY(myvec.lastIndexOf("X", 2) == -1); - - // add an X - myvec << "X"; - QVERIFY(myvec.lastIndexOf("X") == 5); - QVERIFY(myvec.lastIndexOf("X", 5) == 5); - QVERIFY(myvec.lastIndexOf("X", 3) == -1); - - // remove first A - myvec.remove(0); - QVERIFY(myvec.lastIndexOf("A") == 3); - QVERIFY(myvec.lastIndexOf("A", 3) == 3); - QVERIFY(myvec.lastIndexOf("A", 2) == -1); -} - -void tst_QVector::mid() const -{ - QVector list; - list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty"; - - QCOMPARE(list.mid(3, 3), QVector() << "bak" << "buck" << "hello"); - QCOMPARE(list.mid(6, 10), QVector() << "kitty"); - QCOMPARE(list.mid(-1, 20), list); - QCOMPARE(list.mid(4), QVector() << "buck" << "hello" << "kitty"); -} - -template -void tst_QVector::qhash() const -{ - QVector l1, l2; - QCOMPARE(qHash(l1), qHash(l2)); - l1 << SimpleValue::at(0); - l2 << SimpleValue::at(0); - QCOMPARE(qHash(l1), qHash(l2)); -} - -template -void tst_QVector::move() const -{ - QVector list; - list << T_FOO << T_BAR << T_BAZ; - - // move an item - list.move(0, list.count() - 1); - QCOMPARE(list, QVector() << T_BAR << T_BAZ << T_FOO); - - // move it back - list.move(list.count() - 1, 0); - QCOMPARE(list, QVector() << T_FOO << T_BAR << T_BAZ); - - // move an item in the middle - list.move(1, 0); - QCOMPARE(list, QVector() << T_BAR << T_FOO << T_BAZ); -} - -void tst_QVector::moveInt() const -{ - move(); -} - -void tst_QVector::moveMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - move(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::moveCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - move(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -template -void tst_QVector::prepend() const -{ - QVector myvec; - T val1 = SimpleValue::at(0); - T val2 = SimpleValue::at(1); - T val3 = SimpleValue::at(2); - T val4 = SimpleValue::at(3); - T val5 = SimpleValue::at(4); - myvec << val1 << val2 << val3; - - // starts ok - QVERIFY(myvec.size() == 3); - QCOMPARE(myvec.at(0), val1); - - // add something - myvec.prepend(val4); - QCOMPARE(myvec.at(0), val4); - QCOMPARE(myvec.at(1), val1); - QVERIFY(myvec.size() == 4); - - // something else - myvec.prepend(val5); - QCOMPARE(myvec.at(0), val5); - QCOMPARE(myvec.at(1), val4); - QCOMPARE(myvec.at(2), val1); - QVERIFY(myvec.size() == 5); - - // clear and prepend to an empty vector - myvec.clear(); - QVERIFY(myvec.size() == 0); - myvec.prepend(val5); - QVERIFY(myvec.size() == 1); - QCOMPARE(myvec.at(0), val5); -} - -void tst_QVector::prependInt() const -{ - prepend(); -} - -void tst_QVector::prependMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - prepend(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::prependCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - prepend(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::removeAllWithAlias() const -{ - QVector strings; - strings << "One" << "Two" << "Three" << "One" /* must be distinct, but equal */; - QCOMPARE(strings.removeAll(strings.front()), 2); // will trigger asan/ubsan -} - -template -void tst_QVector::remove() const -{ - QVector myvec; - T val1 = SimpleValue::at(1); - T val2 = SimpleValue::at(2); - T val3 = SimpleValue::at(3); - T val4 = SimpleValue::at(4); - myvec << val1 << val2 << val3; - myvec << val1 << val2 << val3; - myvec << val1 << val2 << val3; - // remove middle - myvec.remove(1); - QCOMPARE(myvec, QVector() << val1 << val3 << val1 << val2 << val3 << val1 << val2 << val3); - - // removeOne() - QVERIFY(!myvec.removeOne(val4)); - QVERIFY(myvec.removeOne(val2)); - QCOMPARE(myvec, QVector() << val1 << val3 << val1 << val3 << val1 << val2 << val3); - - QVector myvecCopy = myvec; - QVERIFY(myvecCopy.isSharedWith(myvec)); - // removeAll() - QCOMPARE(myvec.removeAll(val4), 0); - QVERIFY(myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec.removeAll(val1), 3); - QVERIFY(!myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec, QVector() << val3 << val3 << val2 << val3); - myvecCopy = myvec; - QVERIFY(myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec.removeAll(val2), 1); - QVERIFY(!myvecCopy.isSharedWith(myvec)); - QCOMPARE(myvec, QVector() << val3 << val3 << val3); - - // remove rest - myvec.remove(0, 3); - QCOMPARE(myvec, QVector()); -} - -void tst_QVector::removeInt() const -{ - remove(); -} - -void tst_QVector::removeMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - remove(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::removeCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - remove(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -struct RemoveLastTestClass -{ - RemoveLastTestClass() { other = 0; deleted = false; } - RemoveLastTestClass *other; - bool deleted; - ~RemoveLastTestClass() - { - deleted = true; - if (other) - other->other = 0; - } -}; - -void tst_QVector::removeFirstLast() const -{ - // pop_pack - pop_front - QVector t, t2; - t.append(1); - t.append(2); - t.append(3); - t.append(4); - t2 = t; - t.pop_front(); - QCOMPARE(t.size(), 3); - QCOMPARE(t.at(0), 2); - t.pop_back(); - QCOMPARE(t.size(), 2); - QCOMPARE(t.at(0), 2); - QCOMPARE(t.at(1), 3); - - // takefirst - takeLast - int n1 = t2.takeLast(); - QCOMPARE(t2.size(), 3); - QCOMPARE(n1, 4); - QCOMPARE(t2.at(0), 1); - QCOMPARE(t2.at(2), 3); - n1 = t2.takeFirst(); - QCOMPARE(t2.size(), 2); - QCOMPARE(n1, 1); - QCOMPARE(t2.at(0), 2); - QCOMPARE(t2.at(1), 3); - - // remove first - QVector x, y; - x.append(1); - x.append(2); - y = x; - x.removeFirst(); - QCOMPARE(x.size(), 1); - QCOMPARE(y.size(), 2); - QCOMPARE(x.at(0), 2); - - // remove Last - QVector v; - v.resize(2); - v[0].other = &(v[1]); - v[1].other = &(v[0]); - // Check dtor - complex type - QVERIFY(v.at(0).other != 0); - v.removeLast(); - QVERIFY(v.at(0).other == 0); - QCOMPARE(v.at(0).deleted, false); - // check iterator - int count = 0; - for (QVector::const_iterator i = v.constBegin(); i != v.constEnd(); ++i) { - ++count; - QVERIFY(i->other == 0); - QCOMPARE(i->deleted, false); - } - // Check size - QCOMPARE(count, 1); - QCOMPARE(v.size(), 1); - v.removeLast(); - QCOMPARE(v.size(), 0); - // Check if we do correct realloc - QVector v2, v3; - v2.append(1); - v2.append(2); - v3 = v2; // shared - v2.removeLast(); - QCOMPARE(v2.size(), 1); - QCOMPARE(v3.size(), 2); - QCOMPARE(v2.at(0), 1); - QCOMPARE(v3.at(0), 1); - QCOMPARE(v3.at(1), 2); - - // Remove last with shared - QVector z1, z2; - z1.append(9); - z2 = z1; - z1.removeLast(); - QCOMPARE(z1.size(), 0); - QCOMPARE(z2.size(), 1); - QCOMPARE(z2.at(0), 9); -} - - -void tst_QVector::resizePOD_data() const -{ - QTest::addColumn >("vector"); - QTest::addColumn("size"); - - QVERIFY(!QTypeInfo::isComplex); - QVERIFY(!QTypeInfo::isStatic); - - QVector null; - QVector empty(0, 5); - QVector emptyReserved; - QVector nonEmpty; - QVector nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << 0 << 1 << 2 << 3 << 4; - nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizePOD() const -{ - QFETCH(QVector, vector); - QFETCH(int, size); - - const int oldSize = vector.size(); - - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i] == 0); // check initialization - - const int capacity = vector.capacity(); - - vector.clear(); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.capacity() <= capacity); -} - -void tst_QVector::resizeComplexMovable_data() const -{ - QTest::addColumn >("vector"); - QTest::addColumn("size"); - - QVERIFY(QTypeInfo::isComplex); - QVERIFY(!QTypeInfo::isStatic); - - QVector null; - QVector empty(0, 'Q'); - QVector emptyReserved; - QVector nonEmpty; - QVector nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizeComplexMovable() const -{ - const int items = Movable::counter.loadAcquire(); - { - QFETCH(QVector, vector); - QFETCH(int, size); - - const int oldSize = vector.size(); - - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i] == 'j'); // check initialization - - const int capacity = vector.capacity(); - - vector.resize(0); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.capacity() <= capacity); - } - QCOMPARE(items, Movable::counter.loadAcquire()); -} - -void tst_QVector::resizeComplex_data() const -{ - QTest::addColumn >("vector"); - QTest::addColumn("size"); - - QVERIFY(QTypeInfo::isComplex); - QVERIFY(QTypeInfo::isStatic); - - QVector null; - QVector empty(0, '0'); - QVector emptyReserved; - QVector nonEmpty; - QVector nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - QTest::newRow("null") << null << 10; - QTest::newRow("empty") << empty << 10; - QTest::newRow("emptyReserved") << emptyReserved << 10; - QTest::newRow("nonEmpty") << nonEmpty << 10; - QTest::newRow("nonEmptyReserved") << nonEmptyReserved << 10; -} - -void tst_QVector::resizeComplex() const -{ - const int items = Custom::counter.loadAcquire(); - { - QFETCH(QVector, vector); - QFETCH(int, size); - - int oldSize = vector.size(); - vector.resize(size); - QCOMPARE(vector.size(), size); - QVERIFY(vector.capacity() >= size); - for (int i = oldSize; i < size; ++i) - QVERIFY(vector[i].i == 'j'); // check default initialization - - const int capacity = vector.capacity(); - - vector.resize(0); - QCOMPARE(vector.size(), 0); - QVERIFY(vector.isEmpty()); - QVERIFY(vector.capacity() <= capacity); - } - QCOMPARE(Custom::counter.loadAcquire(), items); -} - -void tst_QVector::resizeCtorAndDtor() const -{ - const int items = Custom::counter.loadAcquire(); - { - QVector null; - QVector empty(0, '0'); - QVector emptyReserved; - QVector nonEmpty; - QVector nonEmptyReserved; - - emptyReserved.reserve(10); - nonEmptyReserved.reserve(15); - nonEmpty << '0' << '1' << '2' << '3' << '4'; - nonEmptyReserved << '0' << '1' << '2' << '3' << '4' << '5' << '6'; - QVERIFY(emptyReserved.capacity() >= 10); - QVERIFY(nonEmptyReserved.capacity() >= 15); - - // start playing with vectors - null.resize(21); - nonEmpty.resize(2); - emptyReserved.resize(0); - nonEmpty.resize(0); - nonEmptyReserved.resize(2); - } - QCOMPARE(Custom::counter.loadAcquire(), items); -} - -void tst_QVector::reverseIterators() const -{ - QVector v; - v << 1 << 2 << 3 << 4; - QVector vr = v; - std::reverse(vr.begin(), vr.end()); - const QVector &cvr = vr; - QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); - QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); - QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); - QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); - QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); - QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); -} - -template -void tst_QVector::size() const -{ - // zero size - QVector myvec; - QVERIFY(myvec.size() == 0); - - // grow - myvec.append(SimpleValue::at(0)); - QVERIFY(myvec.size() == 1); - myvec.append(SimpleValue::at(1)); - QVERIFY(myvec.size() == 2); - - // shrink - myvec.remove(0); - QVERIFY(myvec.size() == 1); - myvec.remove(0); - QVERIFY(myvec.size() == 0); -} - -void tst_QVector::sizeInt() const -{ - size(); -} - -void tst_QVector::sizeMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - size(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::sizeCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - size(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -// ::squeeze() is tested in ::capacity(). - -void tst_QVector::startsWith() const -{ - QVector myvec; - - // empty vector - QVERIFY(!myvec.startsWith(1)); - - // add the one, should work - myvec.prepend(1); - QVERIFY(myvec.startsWith(1)); - - // add something else, fails now - myvec.prepend(3); - QVERIFY(!myvec.startsWith(1)); - - // remove it again :) - myvec.remove(0); - QVERIFY(myvec.startsWith(1)); -} - -template -void tst_QVector::swap() const -{ - QVector v1, v2; - T val1 = SimpleValue::at(0); - T val2 = SimpleValue::at(1); - T val3 = SimpleValue::at(2); - T val4 = SimpleValue::at(3); - T val5 = SimpleValue::at(4); - T val6 = SimpleValue::at(5); - v1 << val1 << val2 << val3; - v2 << val4 << val5 << val6; - - v1.swap(v2); - QCOMPARE(v1,QVector() << val4 << val5 << val6); - QCOMPARE(v2,QVector() << val1 << val2 << val3); -} - -void tst_QVector::swapInt() const -{ - swap(); -} - -void tst_QVector::swapMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - swap(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::swapCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - swap(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::toList() const -{ - QVector myvec; - myvec << "A" << "B" << "C"; - - // make sure it converts and doesn't modify the original vector - QCOMPARE(myvec.toList(), QList() << "A" << "B" << "C"); - QCOMPARE(myvec, QVector() << "A" << "B" << "C"); -} - -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -void tst_QVector::toStdVector() const -{ - QVector myvec; - myvec << "A" << "B" << "C"; - - std::vector svec = myvec.toStdVector(); - QCOMPARE(svec.at(0), QLatin1String("A")); - QCOMPARE(svec.at(1), QLatin1String("B")); - QCOMPARE(svec.at(2), QLatin1String("C")); - - QCOMPARE(myvec, QVector() << "A" << "B" << "C"); -} -#endif - -void tst_QVector::value() const -{ - QVector myvec; - myvec << "A" << "B" << "C"; - - // valid calls - QCOMPARE(myvec.value(0), QLatin1String("A")); - QCOMPARE(myvec.value(1), QLatin1String("B")); - QCOMPARE(myvec.value(2), QLatin1String("C")); - - // default calls - QCOMPARE(myvec.value(-1), QString()); - QCOMPARE(myvec.value(3), QString()); - - // test calls with a provided default, valid calls - QCOMPARE(myvec.value(0, QLatin1String("default")), QLatin1String("A")); - QCOMPARE(myvec.value(1, QLatin1String("default")), QLatin1String("B")); - QCOMPARE(myvec.value(2, QLatin1String("default")), QLatin1String("C")); - - // test calls with a provided default that will return the default - QCOMPARE(myvec.value(-1, QLatin1String("default")), QLatin1String("default")); - QCOMPARE(myvec.value(3, QLatin1String("default")), QLatin1String("default")); -} - -void tst_QVector::testOperators() const -{ - QVector myvec; - myvec << "A" << "B" << "C"; - QVector myvectwo; - myvectwo << "D" << "E" << "F"; - QVector combined; - combined << "A" << "B" << "C" << "D" << "E" << "F"; - - // != - QVERIFY(myvec != myvectwo); - - // + - QCOMPARE(myvec + myvectwo, combined); - QCOMPARE(myvec, QVector() << "A" << "B" << "C"); - QCOMPARE(myvectwo, QVector() << "D" << "E" << "F"); - - // += - myvec += myvectwo; - QCOMPARE(myvec, combined); - - // == - QVERIFY(myvec == combined); - - // <, >, <=, >= - QVERIFY(!(myvec < combined)); - QVERIFY(!(myvec > combined)); - QVERIFY( myvec <= combined); - QVERIFY( myvec >= combined); - combined.push_back("G"); - QVERIFY( myvec < combined); - QVERIFY(!(myvec > combined)); - QVERIFY( myvec <= combined); - QVERIFY(!(myvec >= combined)); - QVERIFY(combined > myvec); - QVERIFY(combined >= myvec); - - // [] - QCOMPARE(myvec[0], QLatin1String("A")); - QCOMPARE(myvec[1], QLatin1String("B")); - QCOMPARE(myvec[2], QLatin1String("C")); - QCOMPARE(myvec[3], QLatin1String("D")); - QCOMPARE(myvec[4], QLatin1String("E")); - QCOMPARE(myvec[5], QLatin1String("F")); -} - - -int fooCtor; -int fooDtor; - -struct Foo -{ - int *p; - - Foo() { p = new int; ++fooCtor; } - Foo(const Foo &other) { Q_UNUSED(other); p = new int; ++fooCtor; } - - void operator=(const Foo & /* other */) { } - - ~Foo() { delete p; ++fooDtor; } -}; - -void tst_QVector::reserve() -{ - fooCtor = 0; - fooDtor = 0; - { - QVector a; - a.resize(2); - QCOMPARE(fooCtor, 2); - QVector b(a); - b.reserve(1); - QCOMPARE(b.size(), a.size()); - QCOMPARE(fooDtor, 0); - } - QCOMPARE(fooCtor, fooDtor); -} - -// This is a regression test for QTBUG-51758 -void tst_QVector::reserveZero() -{ - QVector vec; - vec.detach(); - vec.reserve(0); // should not crash - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.squeeze(); - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.reserve(-1); - QCOMPARE(vec.size(), 0); - QCOMPARE(vec.capacity(), 0); - vec.append(42); - QCOMPARE(vec.size(), 1); - QVERIFY(vec.capacity() >= 1); -} - -template -void tst_QVector::initializeList() -{ - T val1(SimpleValue::at(1)); - T val2(SimpleValue::at(2)); - T val3(SimpleValue::at(3)); - T val4(SimpleValue::at(4)); - - QVector v1 {val1, val2, val3}; - QCOMPARE(v1, QVector() << val1 << val2 << val3); - QCOMPARE(v1, (QVector {val1, val2, val3})); - - QVector> v2{ v1, {val4}, QVector(), {val1, val2, val3} }; - QVector> v3; - v3 << v1 << (QVector() << val4) << QVector() << v1; - QCOMPARE(v3, v2); - - QVector v4({}); - QCOMPARE(v4.size(), 0); -} - -void tst_QVector::initializeListInt() -{ - initializeList(); -} - -void tst_QVector::initializeListMovable() -{ - const int instancesCount = Movable::counter.loadAcquire(); - initializeList(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::initializeListCustom() -{ - const int instancesCount = Custom::counter.loadAcquire(); - initializeList(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -void tst_QVector::const_shared_null() -{ - QVector v2; - QVERIFY(!v2.isDetached()); -} - -template -void tst_QVector::detach() const -{ - { - // detach an empty vector - QVector v; - v.detach(); - QVERIFY(!v.isDetached()); - QCOMPARE(v.size(), 0); - QCOMPARE(v.capacity(), 0); - } - { - // detach an empty referenced vector - QVector v; - QVector ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(!v.isDetached()); - QCOMPARE(v.size(), 0); - QCOMPARE(v.capacity(), 0); - } - { - // detach a not empty referenced vector - QVector v(31); - QVector ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 31); - QCOMPARE(v.capacity(), 31); - } - { - // detach a not empty vector - QVector v(31); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 31); - QCOMPARE(v.capacity(), 31); - } - { - // detach a not empty vector with preallocated space - QVector v(3); - v.reserve(8); - QVector ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 3); - QCOMPARE(v.capacity(), 8); - } - { - // detach a not empty vector with preallocated space - QVector v(3); - v.reserve(8); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 3); - QCOMPARE(v.capacity(), 8); - } - { - // detach a not empty, initialized vector - QVector v(7, SimpleValue::at(1)); - QVector ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue::at(1)); - } - { - // detach a not empty, initialized vector - QVector v(7, SimpleValue::at(2)); - QVERIFY(v.isDetached()); - v.detach(); // detaching a detached vector - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue::at(2)); - } - { - // detach a not empty, initialized vector with preallocated space - QVector v(7, SimpleValue::at(3)); - v.reserve(31); - QVector ref(v); - QVERIFY(!v.isDetached()); - v.detach(); - QVERIFY(v.isDetached()); - QCOMPARE(v.size(), 7); - QCOMPARE(v.capacity(), 31); - for (int i = 0; i < v.size(); ++i) - QCOMPARE(v[i], SimpleValue::at(3)); - } -} - -void tst_QVector::detachInt() const -{ - detach(); -} - -void tst_QVector::detachMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - detach(); - QCOMPARE(instancesCount, Movable::counter.loadAcquire()); -} - -void tst_QVector::detachCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - detach(); - QCOMPARE(instancesCount, Custom::counter.loadAcquire()); -} - -static QAtomicPointer > detachThreadSafetyDataInt; -static QAtomicPointer > detachThreadSafetyDataMovable; -static QAtomicPointer > detachThreadSafetyDataCustom; - -template QAtomicPointer > *detachThreadSafetyData(); -template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataInt; } -template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataMovable; } -template<> QAtomicPointer > *detachThreadSafetyData() { return &detachThreadSafetyDataCustom; } - -static QSemaphore detachThreadSafetyLock; - -template -void tst_QVector::detachThreadSafety() const -{ - delete detachThreadSafetyData()->fetchAndStoreOrdered(new QVector(SimpleValue::vector(400))); - - static const uint threadsCount = 5; - - struct : QThread { - void run() override - { - QVector copy(*detachThreadSafetyData()->loadRelaxed()); - QVERIFY(!copy.isDetached()); - detachThreadSafetyLock.release(); - detachThreadSafetyLock.acquire(100); - copy.detach(); - } - } threads[threadsCount]; - - for (uint i = 0; i < threadsCount; ++i) - threads[i].start(); - QThread::yieldCurrentThread(); - detachThreadSafetyLock.acquire(threadsCount); - - // destroy static original data - delete detachThreadSafetyData()->fetchAndStoreOrdered(0); - - QVERIFY(threadsCount < 100); - detachThreadSafetyLock.release(threadsCount * 100); - QThread::yieldCurrentThread(); - - for (uint i = 0; i < threadsCount; ++i) - threads[i].wait(); -} - -void tst_QVector::detachThreadSafetyInt() const -{ - for (uint i = 0; i < 128; ++i) - detachThreadSafety(); -} - -void tst_QVector::detachThreadSafetyMovable() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - for (uint i = 0; i < 128; ++i) { - detachThreadSafety(); - QCOMPARE(Movable::counter.loadAcquire(), instancesCount); - } -} - -void tst_QVector::detachThreadSafetyCustom() const -{ - const int instancesCount = Custom::counter.loadAcquire(); - for (uint i = 0; i < 128; ++i) { - detachThreadSafety(); - QCOMPARE(Custom::counter.loadAcquire(), instancesCount); - } -} - -void tst_QVector::insertMove() const -{ - const int instancesCount = Movable::counter.loadAcquire(); - { - QVector vec; - vec.reserve(7); - Movable m0; - Movable m1; - Movable m2; - Movable m3; - Movable m4; - Movable m5; - Movable m6; - - vec.append(std::move(m3)); - QVERIFY(m3.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m3)); - vec.push_back(std::move(m4)); - QVERIFY(m4.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m3)); - QVERIFY(vec.at(1).wasConstructedAt(&m4)); - vec.prepend(std::move(m1)); - QVERIFY(m1.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m3)); - QVERIFY(vec.at(2).wasConstructedAt(&m4)); - vec.insert(1, std::move(m2)); - QVERIFY(m2.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - vec += std::move(m5); - QVERIFY(m5.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - QVERIFY(vec.at(4).wasConstructedAt(&m5)); - vec << std::move(m6); - QVERIFY(m6.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m1)); - QVERIFY(vec.at(1).wasConstructedAt(&m2)); - QVERIFY(vec.at(2).wasConstructedAt(&m3)); - QVERIFY(vec.at(3).wasConstructedAt(&m4)); - QVERIFY(vec.at(4).wasConstructedAt(&m5)); - QVERIFY(vec.at(5).wasConstructedAt(&m6)); - vec.push_front(std::move(m0)); - QVERIFY(m0.wasConstructedAt(nullptr)); - QVERIFY(vec.at(0).wasConstructedAt(&m0)); - QVERIFY(vec.at(1).wasConstructedAt(&m1)); - QVERIFY(vec.at(2).wasConstructedAt(&m2)); - QVERIFY(vec.at(3).wasConstructedAt(&m3)); - QVERIFY(vec.at(4).wasConstructedAt(&m4)); - QVERIFY(vec.at(5).wasConstructedAt(&m5)); - QVERIFY(vec.at(6).wasConstructedAt(&m6)); - - QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14); - } - QCOMPARE(Movable::counter.loadAcquire(), instancesCount); -} - -void tst_QVector::swapItemsAt() const -{ - QVector v; - v << 0 << 1 << 2 << 3; - - v.swapItemsAt(0, 2); - QCOMPARE(v.at(0), 2); - QCOMPARE(v.at(2), 0); - - auto copy = v; - copy.swapItemsAt(0, 2); - QCOMPARE(v.at(0), 2); - QCOMPARE(v.at(2), 0); - QCOMPARE(copy.at(0), 0); - QCOMPARE(copy.at(2), 2); -} - -void tst_QVector::emplaceInt() -{ - emplaceImpl(); -} - -void tst_QVector::emplaceCustom() -{ - emplaceImpl(); -} - -void tst_QVector::emplaceMovable() -{ - emplaceImpl(); -} - -void tst_QVector::emplaceConsistentWithStdVectorInt() -{ - emplaceConsistentWithStdVectorImpl(); -} - -void tst_QVector::emplaceConsistentWithStdVectorCustom() -{ - emplaceConsistentWithStdVectorImpl(); -} - -void tst_QVector::emplaceConsistentWithStdVectorMovable() -{ - emplaceConsistentWithStdVectorImpl(); -} - -void tst_QVector::emplaceReturnsIterator() -{ - QVector vec; - - vec.emplace(0, 'k')->i = 'p'; - - QCOMPARE(vec[0].i, 'p'); -} - -void tst_QVector::emplaceBack() -{ - QScopedValueRollback rollback(Movable::counter, 0); - - QVector vec; - - vec.emplaceBack('k'); - - QCOMPARE(Movable::counter, 1); -} - -void tst_QVector::emplaceBackReturnsRef() -{ - QVector vec; - - vec.emplaceBack('k').i = 'p'; - - QCOMPARE(vec.at(0).i, 'p'); -} - -void tst_QVector::emplaceWithElementFromTheSameContainer() -{ - QFETCH(int, elementPos); - QFETCH(int, insertPos); - QFETCH(bool, doCopy); - - QVector vec {"a", "b", "c", "d", "e"}; - const QString e = vec[elementPos]; - - if (doCopy) - vec.emplace(insertPos, vec[elementPos]); - else - vec.emplace(insertPos, std::move(vec[elementPos])); - - QCOMPARE(vec[insertPos], e); -} - -void tst_QVector::emplaceWithElementFromTheSameContainer_data() -{ - QTest::addColumn("elementPos"); - QTest::addColumn("insertPos"); - QTest::addColumn("doCopy"); - - for (int i = 0; i < 2; ++i) { - const bool doCopy = i == 0; - const char *opName = doCopy ? "copy" : "move"; - - QTest::addRow("%s: begin -> end" , opName) << 0 << 5 << doCopy; - QTest::addRow("%s: begin -> middle", opName) << 0 << 2 << doCopy; - QTest::addRow("%s: middle -> begin" , opName) << 2 << 0 << doCopy; - QTest::addRow("%s: middle -> end" , opName) << 2 << 5 << doCopy; - QTest::addRow("%s: end -> middle", opName) << 4 << 2 << doCopy; - QTest::addRow("%s: end -> begin" , opName) << 4 << 0 << doCopy; - } -} - -template -void tst_QVector::emplaceImpl() const -{ - QVector vec {'a', 'b', 'c', 'd'}; - - vec.emplace(2, 'k'); - - QCOMPARE(vec[2], T('k')); -} - -template -static void vecEq(const QVector &qVec, const std::vector &stdVec) -{ - QCOMPARE(std::size_t(qVec.size()), stdVec.size()); - QVERIFY(std::equal(qVec.begin(), qVec.end(), stdVec.begin(), stdVec.end())); -} - -template -static void squeezeVec(QVector &qVec, std::vector &stdVec) -{ - qVec.squeeze(); - stdVec.shrink_to_fit(); -} - -template -void tst_QVector::emplaceConsistentWithStdVectorImpl() const -{ - QVector qVec {'a', 'b', 'c', 'd', 'e'}; - std::vector stdVec {'a', 'b', 'c', 'd', 'e'}; - vecEq(qVec, stdVec); - - qVec.emplaceBack('f'); - stdVec.emplace_back('f'); - vecEq(qVec, stdVec); - - qVec.emplace(3, 'g'); - stdVec.emplace(stdVec.begin() + 3, 'g'); - vecEq(qVec, stdVec); - - T t; - // while QVector is safe with regards to emplacing elements moved form itself, it's UB - // for std::vector, so do the moving in two steps there. - qVec.emplaceBack(std::move(qVec[0])); - stdVec.emplace_back(std::move(t = std::move(stdVec[0]))); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplaceBack(std::move(qVec[1])); - stdVec.emplace_back(std::move(t = std::move(stdVec[1]))); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplace(3, std::move(qVec[5])); - stdVec.emplace(stdVec.begin() + 3, std::move(t = std::move(stdVec[5]))); - - vecEq(qVec, stdVec); - - qVec.emplaceBack(qVec[3]); - stdVec.emplace_back((t = stdVec[3])); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplaceBack(qVec[4]); - stdVec.emplace_back((t = stdVec[4])); - vecEq(qVec, stdVec); - - squeezeVec(qVec, stdVec); - - qVec.emplace(5, qVec[7]); - stdVec.emplace(stdVec.begin() + 5, (t = stdVec[7])); - vecEq(qVec, stdVec); -} - -QTEST_MAIN(tst_QVector) -#include "tst_qvector.moc" diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 21dfdf8c47..0557b69e5c 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -16,6 +16,7 @@ SUBDIRS=\ qhash \ qhashfunctions \ qline \ + qlist \ qmakearray \ qmap \ qmargins \ @@ -38,7 +39,6 @@ SUBDIRS=\ qstl \ qtimeline \ qvarlengtharray \ - qvector \ qversionnumber darwin: SUBDIRS += qmacautoreleasepool diff --git a/tests/auto/dbus/qdbusmetatype/tst_qdbusmetatype.cpp b/tests/auto/dbus/qdbusmetatype/tst_qdbusmetatype.cpp index ec3e71ac8f..4b926dcd05 100644 --- a/tests/auto/dbus/qdbusmetatype/tst_qdbusmetatype.cpp +++ b/tests/auto/dbus/qdbusmetatype/tst_qdbusmetatype.cpp @@ -402,7 +402,7 @@ void tst_QDBusMetaType::invalidTypes() else if (qstrcmp(QTest::currentDataTag(), "Invalid7") == 0) QTest::ignoreMessage(QtWarningMsg, "QDBusMarshaller: type `Invalid7' produces invalid D-BUS signature `()' (Did you forget to call beginStructure() ?)"); else if (qstrcmp(QTest::currentDataTag(), "QList") == 0) - QTest::ignoreMessage(QtWarningMsg, "QDBusMarshaller: type `QVector' produces invalid D-BUS signature `a' (Did you forget to call beginStructure() ?)"); + QTest::ignoreMessage(QtWarningMsg, "QDBusMarshaller: type `QList' produces invalid D-BUS signature `a' (Did you forget to call beginStructure() ?)"); staticTypes(); staticTypes(); // run twice: the error messages should be printed once only diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json index 7b025963e2..85751845c4 100644 --- a/tests/auto/tools/moc/allmocs_baseline_in.json +++ b/tests/auto/tools/moc/allmocs_baseline_in.json @@ -1251,7 +1251,7 @@ "required": false, "scriptable": true, "stored": true, - "type": "QVector", + "type": "QList", "user": false, "write": "setFlagsList" } @@ -2699,7 +2699,7 @@ "access": "public", "arguments": [ { - "type": "QVector>" + "type": "QList>" } ], "name": "foo", @@ -2709,7 +2709,7 @@ "access": "public", "arguments": [ { - "type": "QVector>" + "type": "QList>" } ], "name": "foo2", @@ -2719,7 +2719,7 @@ "access": "public", "arguments": [ { - "type": "QVector<::AAA::BaseA*>" + "type": "QList<::AAA::BaseA*>" } ], "name": "bar", @@ -2729,7 +2729,7 @@ "access": "public", "arguments": [ { - "type": "QVector<::AAA::BaseA*>" + "type": "QList<::AAA::BaseA*>" } ], "name": "bar2", @@ -2739,7 +2739,7 @@ "access": "public", "arguments": [ { - "type": "QVector" + "type": "QList" } ], "name": "bar3", diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 4a6d16b45a..05ad63e4ba 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1804,32 +1804,16 @@ signals: class QTBUG12260_defaultTemplate_Object : public QObject { Q_OBJECT public slots: -#if !(defined(Q_CC_GNU) && __GNUC__ == 4 && __GNUC_MINOR__ <= 3) || defined(Q_MOC_RUN) void doSomething(QHash values = QHash() ) { Q_UNUSED(values); } void doSomethingElse(QSharedPointer> 2)> > val = QSharedPointer> 2)> >() ) { Q_UNUSED(val); } -#else - // we want to test the previous function, but gcc < 4.4 seemed to have a bug similar to the one moc has. - typedef QHash WorkaroundGCCBug; - void doSomething(QHash values = WorkaroundGCCBug() ) { Q_UNUSED(values); } - void doSomethingElse(QSharedPointer> 2)> > val - = (QSharedPointer> 2)> >()) ) - { Q_UNUSED(val); } -#endif void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); } -#if defined(Q_MOC_RUN) || (defined(Q_COMPILER_AUTO_TYPE) && !(defined(Q_CC_CLANG) && Q_CC_CLANG < 304)) - // There is no Q_COMPILER_>> but if compiler support auto, it should also support >> - void performSomething(QVector> e = QVector>(8 < 1), - QHash> h = QHash>()) + void performSomething(QList> e = QList>(8 < 1), + QHash> h = QHash>()) { Q_UNUSED(e); Q_UNUSED(h); } -#else - void performSomething(QVector > e = QVector >(), - QHash > h = (QHash >())) - { Q_UNUSED(e); Q_UNUSED(h); } -#endif }; @@ -1838,7 +1822,7 @@ void tst_Moc::QTBUG12260_defaultTemplate() QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomething(QHash)") != -1); QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doAnotherThing(bool,bool)") != -1); QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("doSomethingElse(QSharedPointer>2)>>)") != -1); - QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("performSomething(QVector>,QHash>)") != -1); + QVERIFY(QTBUG12260_defaultTemplate_Object::staticMetaObject.indexOfSlot("performSomething(QList>,QHash>)") != -1); } void tst_Moc::notifyError() -- cgit v1.2.3