transform_inclusive_scan
without initial valueSection: 26.10.11 [transform.inclusive.scan] Status: New Submitter: Agustín K-ballo Bergé Opened: 2020-07-07 Last modified: 2020-09-06
Priority: 3
View all issues with New status.
Discussion:
The requirements for the overloads of std::transform_inclusive_scan
without an initial value incorrectly assume that the internal accumulator uses
the iterator's value type, as it does for std::inclusive_scan
, rather
than the transformed type of the iterator's value type, as it was intended.
std::string
to be convertible to int
:
auto vs = {0, 1, 2}; std::transform_inclusive_scan( vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, ";"), [](std::string x, std::string y) { return x + y; }, [](int x) { return std::to_string(x); });
libstdc++ and Microsoft's STL accept the snippet, producing 0;01;012;
as expected, libc++ strictly conforms to the standard and rejects it.
[2020-07-17; Priority set to 3 in telecon]
Proposed resolution:
This wording is relative to N4861.
[Drafting note: Current implementations that accept the code, do some form of
auto acc = unary_op(*first);
, therefore the following proposed wording usesdecay_t
instead of e.g.remove_cvref_t
.]
Modify 26.10.11 [transform.inclusive.scan] as indicated:
template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op); template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation, class T> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation, class T> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init);-1- Let
-2- […]U
bethe value type ofdecltype(first)
decay_t<decltype(unary_op(*first))>
.