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>
bb10
Marc Mutz 2015-07-19 10:37:49 +02:00
parent 8d1d12a328
commit 4ea3c0ba80
5 changed files with 69 additions and 2 deletions

View File

@ -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");

View File

@ -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

View File

@ -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()
{

View File

@ -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

View File

@ -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;