QVarLengthArray: simplify / optimize assign(It, It)

After many failed attempts at addressing my dissatisfaction with the
if (n) checks, I finally realized that the problem is the

    while (first != last && end != end())

loop, which, when exited, gives no indication as to _why_ it was
exited. Any attempt to re-construct the exit condition must needs
re-check something that should be known already.

To fix, then, use a while (true) loop and react on first == last and
dst == end() separately.

As a drive-by, cache end().

Task-number: QTBUG-106200
Change-Id: Ic873774451df4102163e6e65d93c35e5dcbbb037
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2023-04-28 07:12:43 +02:00
parent 5a3ac484db
commit 87e90a265f

View File

@ -790,27 +790,28 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *arr
}
auto dst = begin();
while (first != last && dst != end()) {
*dst = *first; // reuse initialized buffer
const auto dend = end();
while (true) {
if (first == last) { // ran out of elements to assign
std::destroy(dst, dend);
break;
}
if (dst == dend) { // ran out of existing elements to overwrite
if constexpr (IsFwdIt) {
dst = std::uninitialized_copy(first, last, dst);
break;
} else {
do {
emplace_back_impl(prealloc, array, *first);
} while (++first != last);
return; // size() is already correct (and dst invalidated)!
}
}
*dst = *first; // overwrite existing element
++dst;
++first;
}
qsizetype n;
if constexpr (IsFwdIt) {
dst = std::uninitialized_copy(first, last, dst);
n = dst - begin();
if (n > s) // otherwise: readjust 's' in erase() later
s = n;
} else {
n = dst - begin();
while (first != last) {
emplace_back_impl(prealloc, array, *first);
++first;
++n;
}
}
erase(data() + n, data() + size());
this->s = dst - begin();
}
template <class T>