This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3222. P0574R1 introduced preconditions on non-existent parameters

Section: 25.10.9 [inclusive.scan], 25.10.11 [transform.inclusive.scan] Status: C++20 Submitter: Jonathan Wakely Opened: 2019-06-18 Last modified: 2021-02-25

Priority: 0

View all issues with C++20 status.

Discussion:

after applying P0574R1 to the working draft, 25.10.11 [transform.inclusive.scan] bullet 1.1 says "If `init` is provided, […]; otherwise, `ForwardIterator1`'s value type shall be […]." 25.10.11 [transform.inclusive.scan] bullet 1.2 says "If `init` is provided, […]; otherwise, […] shall be convertible to `ForwardIterator1`'s value type."

For the first overload `init` is not provided, but there is no `ForwardIterator1`, so these requirements cannot be met. The requirements for the first overload need to be stated in terms of `InputIterator`'s value type, not `ForwardIterator1`'s value type.

The same problem exists in 25.10.9 [inclusive.scan]. 25.10.12 [adjacent.difference] solves this problem by saying "Let `T` be the value type of `decltype(first)`".

[2019-07 Issue Prioritization]

Status to Tentatively Ready after five positive votes on the reflector.

Proposed resolution:

This wording is relative to N4820.

1. Modify 25.10.9 [inclusive.scan] as indicated:

   >     template<class InputIterator, class OutputIterator, class BinaryOperation>
   >       OutputIterator inclusive_scan(InputIterator first, InputIterator last,
   >                                     OutputIterator result, BinaryOperation binary_op);
   >     template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
   >              class BinaryOperation>
   >       ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec,
   >                                       ForwardIterator1 first, ForwardIterator1 last,
   >                                       ForwardIterator2 result, BinaryOperation binary_op);
   >     template<class InputIterator, class OutputIterator, class BinaryOperation, class T>
   >       OutputIterator inclusive_scan(InputIterator first, InputIterator last,
   >                                     OutputIterator result, BinaryOperation binary_op, T init);
   >     template<class ExecutionPolicy,
   >              class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class T>
   >       ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec,
   >                                       ForwardIterator1 first, ForwardIterator1 last,
   >                                       ForwardIterator2 result, BinaryOperation binary_op, T init);

   > > -?- Let `U` be the value type of `decltype(first)`.

   > > -3- Requires:

   > > 1. (3.1) — If `init` is provided, `T` shall be Cpp17MoveConstructible (Table 26); otherwise, `ForwardIterator1`'s value type `U` shall be Cpp17MoveConstructible.

   > > 2. (3.2) — If `init` is provided, all of `binary_op(init, init)`, `binary_op(init, *first)`, and `binary_op(*first, *first)` shall be convertible to `T`; otherwise, `binary_op(*first, *first)` shall be convertible to `ForwardIterator1`'s value type `U`.

   > > 3. (3.3) — `binary_op` shall neither invalidate iterators or subranges, nor modify elements in the ranges `[first, last]` or `[result, result + (last - first)]`.

2. Modify 25.10.11 [transform.inclusive.scan] as indicated:

   >     template<class InputIterator, class OutputIterator,
   >              class BinaryOperation, class UnaryOperation>
   >       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>
   >       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);

   > > -?- Let `U` be the value type of `decltype(first)`.

   > > -1- Requires:

   > > 1. (1.1) — If `init` is provided, `T` shall be Cpp17MoveConstructible (Table 26); otherwise, `ForwardIterator1`'s value type `U` shall be Cpp17MoveConstructible.

   > > 2. (1.2) — If `init` is provided, all of

   > >    1. (1.2.1) — `binary_op(init, init)`,

   > >    2. (1.2.2) — `binary_op(init, unary_op(*first))`, and

   > >    3. (1.2.3) — `binary_op(unary_op(*first), unary_op(*first))`

   > >    shall be convertible to `T`; otherwise, `binary_op(unary_op(*first), unary_op(*first))` shall be convertible to `ForwardIterator1`'s value type `U`.

   > > 3. (1.3) — Neither `unary_op` nor `binary_op` shall invalidate iterators or subranges, nor modify elements in the ranges `[first, last]` or `[result, result + (last - first)]`.