From 87e90a265f6b07b489ea249cc00b46f13e879d83 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 28 Apr 2023 07:12:43 +0200 Subject: [PATCH] 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 --- src/corelib/tools/qvarlengtharray.h | 37 +++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index b4b9c96fb3..b91825af80 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -790,27 +790,28 @@ Q_OUTOFLINE_TEMPLATE void QVLABase::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