summaryrefslogtreecommitdiff
path: root/src/corelib/tools/qvarlengtharray.h
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2023-02-16 11:23:18 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2023-02-24 16:10:11 +0100
commit2457dd8bd0a0a2be567173e3bb9dbfeb1318a02b (patch)
tree8e68bca7580b98c6ac61c8826e7e11c4ddfd968e /src/corelib/tools/qvarlengtharray.h
parentcb15967014196c03a32bf2423aa350716f1d2dff (diff)
downloadqtbase-2457dd8bd0a0a2be567173e3bb9dbfeb1318a02b.tar.gz
QVLA: Optimize assign() for non-throwing copies
Change-Id: I39e2bef482fa638a6d197623759b5163fc7cc3a6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qvarlengtharray.h')
-rw-r--r--src/corelib/tools/qvarlengtharray.h23
1 files changed, 17 insertions, 6 deletions
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index a35d6cce40..a47530219f 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -779,7 +779,10 @@ template <typename Iterator>
Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last)
{
// This function only provides the basic exception guarantee.
- if constexpr (std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>) {
+ constexpr bool IsFwdIt =
+ std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category,
+ std::forward_iterator_tag>;
+ if constexpr (IsFwdIt) {
const qsizetype n = std::distance(first, last);
if (n > capacity())
reallocate_impl(prealloc, array, 0, n); // clear & reserve n
@@ -792,11 +795,19 @@ Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *arr
++first;
}
- qsizetype n = dst - begin();
- while (first != last) {
- emplace_back_impl(prealloc, array, *first);
- ++first;
- ++n;
+ qsizetype n = 0;
+ if constexpr (IsFwdIt && noexcept(T(*first))) {
+ 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());
}