QList: Add a append(QList &&) overload
We already had append(const QList &) and now there's an overload taking an rvalue reference. Change-Id: Id2fbc6c57badebebeee7b80d15bb333270fa4e19 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
0c53f8ba98
commit
5d7be66fd7
@ -239,6 +239,7 @@ public:
|
||||
void append(const_iterator i1, const_iterator i2);
|
||||
void append(rvalue_ref t) { emplaceBack(std::move(t)); }
|
||||
void append(const QList<T> &l) { append(l.constBegin(), l.constEnd()); }
|
||||
void append(QList<T> &&l);
|
||||
void prepend(rvalue_ref t);
|
||||
void prepend(const T &t);
|
||||
|
||||
@ -434,14 +435,19 @@ public:
|
||||
|
||||
// comfort
|
||||
QList<T> &operator+=(const QList<T> &l) { append(l.cbegin(), l.cend()); return *this; }
|
||||
QList<T> &operator+=(QList<T> &&l) { append(std::move(l)); return *this; }
|
||||
inline QList<T> operator+(const QList<T> &l) const
|
||||
{ QList n = *this; n += l; return n; }
|
||||
inline QList<T> operator+(QList<T> &&l) const
|
||||
{ QList n = *this; n += std::move(l); return n; }
|
||||
inline QList<T> &operator+=(const T &t)
|
||||
{ append(t); return *this; }
|
||||
inline QList<T> &operator<< (const T &t)
|
||||
{ append(t); return *this; }
|
||||
inline QList<T> &operator<<(const QList<T> &l)
|
||||
{ *this += l; return *this; }
|
||||
inline QList<T> &operator<<(QList<T> &&l)
|
||||
{ *this += std::move(l); return *this; }
|
||||
inline QList<T> &operator+=(rvalue_ref t)
|
||||
{ append(std::move(t)); return *this; }
|
||||
inline QList<T> &operator<<(rvalue_ref t)
|
||||
@ -579,6 +585,33 @@ inline void QList<T>::append(const_iterator i1, const_iterator i2)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void QList<T>::append(QList<T> &&other)
|
||||
{
|
||||
if (other.isEmpty())
|
||||
return;
|
||||
if (other.d->needsDetach() || !std::is_nothrow_move_constructible_v<T>)
|
||||
return append(other);
|
||||
|
||||
const size_t newSize = size() + other.size();
|
||||
if (d->needsDetach() || newSize > d->allocatedCapacity()) {
|
||||
DataPointer detached(Data::allocate(d->detachCapacity(newSize),
|
||||
d->detachFlags() | Data::GrowsForward));
|
||||
|
||||
if (!d->needsDetach())
|
||||
detached->moveAppend(begin(), end());
|
||||
else
|
||||
detached->copyAppend(cbegin(), cend());
|
||||
detached->moveAppend(other.begin(), other.end());
|
||||
|
||||
d.swap(detached);
|
||||
} else {
|
||||
// we're detached and we can just move data around
|
||||
d->moveAppend(other.begin(), other.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline typename QList<T>::iterator
|
||||
QList<T>::insert(qsizetype i, qsizetype n, parameter_type t)
|
||||
|
@ -670,6 +670,15 @@
|
||||
\sa operator<<(), operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> void QList<T>::append(QList<T> &&value)
|
||||
\overload
|
||||
|
||||
\since 6.0
|
||||
|
||||
Moves the items of the \a value list to the end of this list.
|
||||
|
||||
\sa operator<<(), operator+=()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <typename T> void QList<T>::prepend(const T &value)
|
||||
@ -1290,6 +1299,14 @@
|
||||
\sa operator+(), append()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QList<T> &QList<T>::operator+=(QList<T> &&other)
|
||||
\since 6.0
|
||||
|
||||
\overload
|
||||
|
||||
\sa operator+(), append()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> void QList<T>::operator+=(const T &value)
|
||||
|
||||
\overload
|
||||
@ -1315,6 +1332,14 @@
|
||||
\sa operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QList<T> QList<T>::operator+(QList<T> &&other) const
|
||||
\since 6.0
|
||||
|
||||
\overload
|
||||
|
||||
\sa operator+=()
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QList<T> &QList<T>::operator<<(const T &value)
|
||||
|
||||
Appends \a value to the list and returns a reference to this list.
|
||||
@ -1336,6 +1361,12 @@
|
||||
Appends \a other to the list and returns a reference to the list.
|
||||
*/
|
||||
|
||||
/*! \fn template <typename T> QList<T> &QList<T>::operator<<(QList<T> &&other)
|
||||
\since 6.0
|
||||
|
||||
\overload
|
||||
*/
|
||||
|
||||
/*! \typedef QList::iterator
|
||||
|
||||
The QList::iterator typedef provides an STL-style non-const
|
||||
|
@ -216,6 +216,7 @@ private slots:
|
||||
void appendMovable() const;
|
||||
void appendCustom() const;
|
||||
void appendRvalue() const;
|
||||
void appendList() const;
|
||||
void at() const;
|
||||
void capacityInt() const;
|
||||
void capacityMovable() const;
|
||||
@ -695,6 +696,200 @@ void tst_QList::appendRvalue() const
|
||||
QCOMPARE(v.back(), QString("world"));
|
||||
}
|
||||
|
||||
struct ConstructionCounted
|
||||
{
|
||||
ConstructionCounted(int i) : i(i) { }
|
||||
ConstructionCounted(ConstructionCounted &&other) noexcept
|
||||
: i(other.i), copies(other.copies), moves(other.moves + 1)
|
||||
{
|
||||
// set to some easily noticeable values
|
||||
other.i = -64;
|
||||
other.copies = -64;
|
||||
other.moves = -64;
|
||||
}
|
||||
ConstructionCounted &operator=(ConstructionCounted &&other) noexcept
|
||||
{
|
||||
i = other.i;
|
||||
copies = other.copies;
|
||||
moves = other.moves + 1;
|
||||
// set to some easily noticeable values
|
||||
other.i = -64;
|
||||
other.copies = -64;
|
||||
other.moves = -64;
|
||||
return *this;
|
||||
}
|
||||
ConstructionCounted(const ConstructionCounted &other) noexcept
|
||||
: i(other.i), copies(other.copies + 1), moves(other.moves)
|
||||
{
|
||||
}
|
||||
ConstructionCounted &operator=(const ConstructionCounted &other) noexcept
|
||||
{
|
||||
i = other.i;
|
||||
copies = other.copies + 1;
|
||||
moves = other.moves;
|
||||
return *this;
|
||||
}
|
||||
~ConstructionCounted() = default;
|
||||
|
||||
friend bool operator==(const ConstructionCounted &lhs, const ConstructionCounted &rhs)
|
||||
{
|
||||
return lhs.i == rhs.i;
|
||||
}
|
||||
|
||||
QString toString() { return QString::number(i); }
|
||||
|
||||
int i;
|
||||
int copies = 0;
|
||||
int moves = 0;
|
||||
};
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QTest {
|
||||
char *toString(const ConstructionCounted &cc)
|
||||
{
|
||||
char *str = new char[5];
|
||||
qsnprintf(str, 4, "%d", cc.i);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
void tst_QList::appendList() const
|
||||
{
|
||||
// By const-ref
|
||||
{
|
||||
QList<int> v1 = { 1, 2, 3, 4 };
|
||||
QList<int> v2 = { 5, 6, 7, 8 };
|
||||
v1.append(v2);
|
||||
QCOMPARE(v2.size(), 4);
|
||||
QCOMPARE(v1.size(), 8);
|
||||
QList<int> expected = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
QCOMPARE(v1, expected);
|
||||
|
||||
QList<int> doubleExpected = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
// append self to self
|
||||
v1.append(v1);
|
||||
QCOMPARE(v1.size(), 16);
|
||||
QCOMPARE(v1, doubleExpected);
|
||||
v1.resize(8);
|
||||
|
||||
// append to self, but was shared
|
||||
QList v1_2(v1);
|
||||
v1.append(v1);
|
||||
QCOMPARE(v1_2.size(), 8);
|
||||
QCOMPARE(v1_2, expected);
|
||||
QCOMPARE(v1.size(), 16);
|
||||
QCOMPARE(v1, doubleExpected);
|
||||
v1.resize(8);
|
||||
|
||||
// append empty
|
||||
QList<int> v3;
|
||||
v1.append(v3);
|
||||
|
||||
// append to empty
|
||||
QList<int> v4;
|
||||
v4.append(v1);
|
||||
QCOMPARE(v4, expected);
|
||||
|
||||
v1 = { 1, 2, 3, 4 };
|
||||
// Using operators
|
||||
// <<
|
||||
QList<int> v5;
|
||||
v5 << v1 << v2;
|
||||
QCOMPARE(v5, expected);
|
||||
|
||||
// +=
|
||||
QList<int> v6;
|
||||
v6 += v1;
|
||||
v6 += v2;
|
||||
QCOMPARE(v6, expected);
|
||||
|
||||
// +
|
||||
QCOMPARE(v1 + v2, expected);
|
||||
}
|
||||
// By move
|
||||
{
|
||||
QList<ConstructionCounted> v1 = { 1, 2, 3, 4 };
|
||||
// Sanity check
|
||||
QCOMPARE(v1.at(3).moves, 0);
|
||||
QCOMPARE(v1.at(3).copies, 1); // because of initializer list
|
||||
|
||||
QList<ConstructionCounted> v2 = { 5, 6, 7, 8 };
|
||||
v1.append(std::move(v2));
|
||||
QCOMPARE(v1.size(), 8);
|
||||
QList<ConstructionCounted> expected = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
QCOMPARE(v1, expected);
|
||||
QCOMPARE(v1.at(0).copies, 1);
|
||||
QCOMPARE(v1.at(0).moves, 1);
|
||||
|
||||
QCOMPARE(v1.at(4).copies, 1); // was v2.at(0)
|
||||
QCOMPARE(v1.at(4).moves, 1);
|
||||
|
||||
// append move from empty
|
||||
QList<ConstructionCounted> v3;
|
||||
v1.append(std::move(v3));
|
||||
QCOMPARE(v1.size(), 8);
|
||||
QCOMPARE(v1, expected);
|
||||
|
||||
for (qsizetype i = 0; i < v1.size(); ++i) {
|
||||
const auto &counter = v1.at(i);
|
||||
QCOMPARE(counter.copies, 1);
|
||||
QCOMPARE(counter.moves, 1);
|
||||
}
|
||||
|
||||
// append move to empty
|
||||
QList<ConstructionCounted> v4;
|
||||
v4.reserve(64);
|
||||
v4.append(std::move(v1));
|
||||
QCOMPARE(v4.size(), 8);
|
||||
QCOMPARE(v4, expected);
|
||||
|
||||
for (qsizetype i = 0; i < v4.size(); ++i) {
|
||||
const auto &counter = v4.at(i);
|
||||
QCOMPARE(counter.copies, 1);
|
||||
QCOMPARE(counter.moves, 2);
|
||||
}
|
||||
|
||||
QVERIFY(v4.capacity() >= 64);
|
||||
|
||||
v1.swap(v4); // swap back...
|
||||
|
||||
// append move from shared
|
||||
QList<ConstructionCounted> v5 = { 1, 2, 3, 4 };
|
||||
QList<ConstructionCounted> v5_2(v5);
|
||||
v1.append(std::move(v5_2));
|
||||
QCOMPARE(v1.size(), 12);
|
||||
QList<ConstructionCounted> expectedTwelve = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4 };
|
||||
QCOMPARE(v1, expectedTwelve);
|
||||
QCOMPARE(v5.size(), 4);
|
||||
QList<ConstructionCounted> expectedFour = { 1, 2, 3, 4 };
|
||||
QCOMPARE(v5, expectedFour);
|
||||
|
||||
QCOMPARE(v5.at(0).copies, 1); // from constructing with std::initializer_list
|
||||
QCOMPARE(v5.at(0).moves, 0);
|
||||
|
||||
// Using operators
|
||||
// <<
|
||||
QList<ConstructionCounted> v6;
|
||||
v6 << (QList<ConstructionCounted>() << 1 << 2);
|
||||
v6 << (QList<ConstructionCounted>() << 3 << 4);
|
||||
QCOMPARE(v6, expectedFour);
|
||||
QCOMPARE(v6.at(0).copies, 2);
|
||||
QCOMPARE(v6.at(0).moves, 1);
|
||||
|
||||
// +=
|
||||
QList<ConstructionCounted> v7;
|
||||
v7 += (QList<ConstructionCounted>() << 1 << 2);
|
||||
v7 += (QList<ConstructionCounted>() << 3 << 4);
|
||||
QCOMPARE(v7, expectedFour);
|
||||
|
||||
// +
|
||||
QList<ConstructionCounted> v8;
|
||||
QCOMPARE(v8 + (QList<ConstructionCounted>() << 1 << 2 << 3 << 4), expectedFour);
|
||||
v8 = { 1, 2 };
|
||||
QCOMPARE(v8 + (QList<ConstructionCounted>() << 3 << 4), expectedFour);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QList::at() const
|
||||
{
|
||||
QList<QString> myvec;
|
||||
|
Loading…
Reference in New Issue
Block a user