@@ -108,7 +108,7 @@ exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIte
using namespace __pstl;
return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
- __result, __pstl::__internal::__no_op(), __init, __binary_op,
+ __result, __pstl::__internal::__no_op(), std::move(__init), __binary_op,
/*inclusive=*/std::false_type());
}
@@ -160,11 +160,12 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
{
for (; __first != __last; ++__first, ++__result)
{
- *__result = __init;
+ _Tp __v = std::move(__init);
_PSTL_PRAGMA_FORCEINLINE
- __init = __binary_op(__init, __unary_op(*__first));
+ __init = __binary_op(__v, __unary_op(*__first));
+ *__result = std::move(__v);
}
- return std::make_pair(__result, __init);
+ return std::make_pair(__result, std::move(__init));
}
// Inclusive form
@@ -225,7 +226,7 @@ __pattern_transform_scan(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Fo
_OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
_Inclusive) noexcept
{
- return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
+ return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, std::move(__init), __binary_op, _Inclusive(),
typename _Tag::__is_vector{})
.first;
}
@@ -491,8 +491,8 @@ namespace __detail
{
while (__first != __last)
{
- auto __v = __init;
- __init = __binary_op(__init, *__first);
+ _Tp __v = std::move(__init);
+ __init = __binary_op(__v, *__first);
++__first;
*__result++ = std::move(__v);
}
new file mode 100644
@@ -0,0 +1,46 @@
+// { dg-do run { target c++17 } }
+
+// C++17 29.8.7 [exclusive.scan]
+
+#include <numeric>
+#include <testsuite_hooks.h>
+
+struct Mint
+{
+ Mint(int i = 0) : val(i) { }
+ Mint(Mint&&) = default;
+ Mint& operator=(Mint&&) = default;
+
+ operator int() const { return val; }
+
+private:
+ int val;
+};
+
+void
+test_move_only()
+{
+ const int input[]{10, 20, 30};
+ int output[3];
+ std::exclusive_scan(input, input+3, output, Mint(5), std::plus<int>{});
+ VERIFY( output[0] == 5 );
+ VERIFY( output[1] == 15 );
+ VERIFY( output[2] == 35 );
+}
+
+void
+test_pr108236()
+{
+ int vals[]{1, 2, 3};
+ // Output range is the same as the input range:
+ std::exclusive_scan(vals, vals+3, vals, 99);
+ VERIFY( vals[0] == 99 );
+ VERIFY( vals[1] == 100 );
+ VERIFY( vals[2] == 102 );
+}
+
+int main()
+{
+ test_move_only();
+ test_pr108236();
+}
new file mode 100644
@@ -0,0 +1,50 @@
+// { dg-options "-ltbb" }
+// { dg-do run { target c++17 } }
+// { dg-require-effective-target tbb_backend }
+
+// Bug 108236 std::exclusive_scan with execution policy does not work in-place
+
+#include <numeric>
+#include <execution>
+#include <testsuite_hooks.h>
+
+struct Mint
+{
+ Mint(int i = 0) : val(i) { }
+ Mint(Mint&&) = default;
+ Mint& operator=(Mint&&) = default;
+
+ operator int() const { return val; }
+
+private:
+ int val;
+};
+
+void
+test_move_only()
+{
+ const int input[]{10, 20, 30};
+ int output[3];
+ std::exclusive_scan(std::execution::seq, input, input+3, output, Mint(5),
+ std::plus<int>{});
+ VERIFY( output[0] == 5 );
+ VERIFY( output[1] == 15 );
+ VERIFY( output[2] == 35 );
+}
+
+void
+test_pr108236()
+{
+ int vals[]{1, 2, 3};
+ // Output range is the same as the input range:
+ std::exclusive_scan(std::execution::seq, vals, vals+3, vals, 99);
+ VERIFY( vals[0] == 99 );
+ VERIFY( vals[1] == 100 );
+ VERIFY( vals[2] == 102 );
+}
+
+int main()
+{
+ test_move_only();
+ test_pr108236();
+}