summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2015-07-19 10:37:49 +0200
committerMarc Mutz <marc.mutz@kdab.com>2015-07-19 18:09:27 +0000
commit4ea3c0ba80e55e93ed0e03650325a046a676f73d (patch)
tree821771a7558aa210e2123e46a640677c755297c1
parent8d1d12a32896cca3f9aaae31ae2a3ee28dc8f276 (diff)
QVector: add an rvalue overload of push_back/append
This is low-hanging fruit, for two reasons: 1. The implementation is dead-simple (unlike, say, in QList). 2. It's completely transparent to the QVector user (unlike, say, emplace_back, which can only be used inside an ifdef). Change-Id: Iaf750100cf61ced77aa452f0e4e3c4ec36b29639 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp17
-rw-r--r--src/corelib/tools/qvector.cpp15
-rw-r--r--src/corelib/tools/qvector.h22
-rw-r--r--tests/auto/corelib/tools/qvector/qvector.pro1
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp16
5 files changed, 69 insertions, 2 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
index 77b34c95fc..5def361b83 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp
@@ -84,14 +84,27 @@ for (int i = 0; i < 10; ++i)
//! [7]
-QVector<QString> vector(0);
+QVector<QString> vector;
vector.append("one");
vector.append("two");
-vector.append("three");
+QString three = "three";
+vector.append(three);
// vector: ["one", "two", "three"]
+// three: "three"
//! [7]
+//! [move-append]
+QVector<QString> vector;
+vector.append("one");
+vector.append("two");
+QString three = "three";
+vector.append(std::move(three));
+// vector: ["one", "two", "three"]
+// three: ""
+//! [move-append]
+
+
//! [8]
QVector<QString> vector;
vector.prepend("one");
diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp
index 77afe9d00e..6e5429810e 100644
--- a/src/corelib/tools/qvector.cpp
+++ b/src/corelib/tools/qvector.cpp
@@ -522,6 +522,16 @@
\sa operator<<(), prepend(), insert()
*/
+/*!
+ \fn void QVector::append(T &&value)
+ \since 5.6
+
+ \overload
+
+ Example:
+ \snippet code/src_corelib_tools_qvector.cpp move-append
+*/
+
/*! \fn void QVector::append(const QVector<T> &value)
\overload
@@ -1026,6 +1036,11 @@
to append(\a value).
*/
+/*! \fn void QVector::push_back(T &&value)
+ \since 5.6
+ \overload
+*/
+
/*! \fn void QVector::push_front(const T &value)
This function is provided for STL compatibility. It is equivalent
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 1a7692c0f4..890dbd317d 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -129,6 +129,9 @@ public:
T &operator[](int i);
const T &operator[](int i) const;
void append(const T &t);
+#ifdef Q_COMPILER_RVALUE_REFS
+ void append(T &&t);
+#endif
inline void append(const QVector<T> &l) { *this += l; }
void prepend(const T &t);
void insert(int i, const T &t);
@@ -247,6 +250,9 @@ public:
typedef const_iterator ConstIterator;
typedef int size_type;
inline void push_back(const T &t) { append(t); }
+#ifdef Q_COMPILER_RVALUE_REFS
+ void push_back(T &&t) { append(std::move(t)); }
+#endif
inline void push_front(const T &t) { prepend(t); }
void pop_back() { removeLast(); }
void pop_front() { removeFirst(); }
@@ -643,6 +649,22 @@ void QVector<T>::append(const T &t)
++d->size;
}
+#ifdef Q_COMPILER_RVALUE_REFS
+template <typename T>
+void QVector<T>::append(T &&t)
+{
+ const bool isTooSmall = uint(d->size + 1) > d->alloc;
+ if (!isDetached() || isTooSmall) {
+ QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
+ reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
+ }
+
+ new (d->end()) T(std::move(t));
+
+ ++d->size;
+}
+#endif
+
template <typename T>
void QVector<T>::removeLast()
{
diff --git a/tests/auto/corelib/tools/qvector/qvector.pro b/tests/auto/corelib/tools/qvector/qvector.pro
index 22edde3412..c1e0564915 100644
--- a/tests/auto/corelib/tools/qvector/qvector.pro
+++ b/tests/auto/corelib/tools/qvector/qvector.pro
@@ -1,4 +1,5 @@
CONFIG += testcase parallel_test
+contains(QT_CONFIG, c++11):CONFIG += c++11
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
index e6f008d623..87822bca6f 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -190,6 +190,7 @@ private slots:
void appendInt() const;
void appendMovable() const;
void appendCustom() const;
+ void appendRvalue() const;
void at() const;
void capacityInt() const;
void capacityMovable() const;
@@ -638,6 +639,21 @@ void tst_QVector::appendCustom() const
QCOMPARE(instancesCount, Custom::counter.loadAcquire());
}
+void tst_QVector::appendRvalue() const
+{
+#ifdef Q_COMPILER_RVALUE_REFS
+ QVector<QString> 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"));
+#else
+ QSKIP("This test requires that C++11 move semantics support is enabled in the compiler");
+#endif
+}
+
void tst_QVector::at() const
{
QVector<QString> myvec;