QVarLengthArray: add support for emplacement

Take the rvalue insert() function and turn it into the emplace()
function. Reformulate rvalue-insert using emplace(). Lvalue insert()
is using a different code path, so leave that alone. This way, we
don't need to go overboard with testing.

[ChangeLog][QtCore][QVarLengthArray] Added emplace(), emplace_back().

Change-Id: I3e1400820ae0dd1fe87fd4b4c518f7f40be39f8b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Marc Mutz 2021-08-12 12:13:15 +02:00
parent e7ab888700
commit 29cfea3e82
3 changed files with 52 additions and 5 deletions

View File

@ -288,7 +288,7 @@ public:
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
iterator insert(const_iterator before, qsizetype n, const T &x);
iterator insert(const_iterator before, T &&x);
iterator insert(const_iterator before, T &&x) { return emplace(before, std::move(x)); }
inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(const_iterator begin, const_iterator end);
inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
@ -303,6 +303,11 @@ public:
inline T &back() { return last(); }
inline const T &back() const { return last(); }
void shrink_to_fit() { squeeze(); }
template <typename...Args>
iterator emplace(const_iterator pos, Args &&...args);
template <typename...Args>
T &emplace_back(Args &&...args) { return *emplace(cend(), std::forward<Args>(args)...); }
#ifdef Q_QDOC
template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
@ -612,7 +617,8 @@ inline void QVarLengthArray<T, Prealloc>::replace(qsizetype i, const T &t)
}
template <class T, qsizetype Prealloc>
Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, T &&t)
template <typename...Args>
Q_OUTOFLINE_TEMPLATE auto QVarLengthArray<T, Prealloc>::emplace(const_iterator before, Args &&...args) -> iterator
{
Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
@ -627,14 +633,14 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
new (--j) T(std::move(*--i));
while (i != b)
*--j = std::move(*--i);
*b = std::move(t);
*b = T(std::forward<Args>(args)...);
} else {
new (b) T(std::move(t));
new (b) T(std::forward<Args>(args)...);
}
} else {
T *b = ptr + offset;
memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T));
new (b) T(std::move(t));
new (b) T(std::forward<Args>(args)...);
}
s += 1;
return ptr + offset;

View File

@ -753,6 +753,28 @@
\a before. Returns an iterator pointing at the inserted item.
*/
/*!
\fn template <class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::emplace(const_iterator before, Args &&...args);
\since 6.3
Inserts an item in front of the item pointed to by the iterator
\a before, passing \a args to its constructor.
Returns an iterator pointing at the emplaced item.
*/
/*!
\fn template <class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::emplace_back(Args &&...args);
\since 6.3
Inserts an item at the back of this QVarLengthArray, passing
\a args to its constructor.
Returns a reference to the emplaced item.
*/
/*! \fn template<class T, qsizetype Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, qsizetype count, const T &value)
\since 4.8

View File

@ -70,6 +70,7 @@ class tst_QVarLengthArray : public QObject
private slots:
void append();
void prepend();
void emplace();
void move_int_1() { move_int<1>(); }
void move_int_2() { move_int<2>(); }
void move_int_3() { move_int<3>(); }
@ -164,6 +165,24 @@ void tst_QVarLengthArray::prepend()
QCOMPARE(v.front(), v.back());
}
void tst_QVarLengthArray::emplace()
{
{
QVarLengthArray<QString, 2> strings;
strings.emplace_back();
QCOMPARE(strings.size(), 1);
QCOMPARE(strings.front().isNull(), true);
strings.emplace(strings.begin(), 42, u'x');
QCOMPARE(strings.size(), 2);
QCOMPARE(strings.back().isNull(), true);
QCOMPARE(strings.front(), QString(42, u'x'));
auto &r = strings.emplace_back(42, u'y');
QCOMPARE(&r, &strings.back());
QCOMPARE(strings.size(), 3);
QCOMPARE(strings.back(), QString(42, u'y'));
}
}
template <qsizetype N>
void tst_QVarLengthArray::move_Tracker()
{