summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDennis Oberst <dennis.oberst@qt.io>2023-05-25 11:27:10 +0200
committerMarc Mutz <marc.mutz@qt.io>2023-05-31 14:37:19 +0000
commite07710007b4cf9c0665ac9d5c2b6c7ef588aae0a (patch)
treec045fe8c44b8652214a730c1416c9838735c41dc
parent9da9ca0ac783cd9bf2a0a151e1c4a83f0aeeb54d (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>
-rw-r--r--src/corelib/tools/qarraydatapointer.h8
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));