diff options
author | Dennis Oberst <dennis.oberst@qt.io> | 2023-05-25 11:27:10 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-05-31 14:37:19 +0000 |
commit | e07710007b4cf9c0665ac9d5c2b6c7ef588aae0a (patch) | |
tree | c045fe8c44b8652214a730c1416c9838735c41dc /src | |
parent | 9da9ca0ac783cd9bf2a0a151e1c4a83f0aeeb54d (diff) |
QArrayDataPointer: fix optional projection in assign()
When a custom projection is used in the assign() function, there is a
problem with the optimization step at:
dst = std::uninitialized_copy(first, last, dst);
The issue arises because this copy doesn't respect the custom
projection. To address this problem, we need to ensure that the
optimization is only applied when using the identity projection.
Amends: 7ca633d9a82f90e5bba5e12ba923bfb0a257af63.
Change-Id: I912525c716333ee2c22c419f2bf70201086c5635
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/tools/qarraydatapointer.h | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index ad9ca428de..eb20330f0f 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -315,6 +315,7 @@ public: constexpr bool IsFwdIt = std::is_convertible_v< typename std::iterator_traits<InputIterator>::iterator_category, std::forward_iterator_tag>; + constexpr bool IsIdentity = std::is_same_v<Projection, q20::identity>; if constexpr (IsFwdIt) { const qsizetype n = std::distance(first, last); @@ -379,9 +380,14 @@ public: break; } if (dst == dend) { // ran out of existing elements to overwrite - if constexpr (IsFwdIt) { + if constexpr (IsFwdIt && IsIdentity) { dst = std::uninitialized_copy(first, last, dst); break; + } else if constexpr (IsFwdIt && !IsIdentity + && std::is_nothrow_constructible_v<T, decltype(std::invoke(proj, *first))>) { + for (; first != last; ++dst, ++first) // uninitialized_copy with projection + q20::construct_at(dst, std::invoke(proj, *first)); + break; } else { do { (*this)->emplace(size, std::invoke(proj, *first)); |