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: 7ca633d9a8.

Change-Id: I912525c716333ee2c22c419f2bf70201086c5635
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Dennis Oberst 2023-05-25 11:27:10 +02:00 committed by Marc Mutz
parent 9da9ca0ac7
commit e07710007b

View File

@ -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));