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.

### 3355. The memory algorithms should support move-only input iterators introduced by P1207

Section: 27.11.5 [uninitialized.copy], 27.11.6 [uninitialized.move] Status: C++20 Submitter: Corentin Jabot Opened: 2019-11-12 Last modified: 2021-02-25

Priority: 2

View all other issues in [uninitialized.copy].

View all issues with C++20 status.

Discussion:

P1207 introduced move-only input iterators but did not modify the specialized memory algorithms to support them.

[2020-01 Priority set to 2 after review on the reflector.]

[2020-02 Status to Immediate on Friday morning in Prague.]

Proposed resolution:

This wording is relative to N4842.

1. Modify 27.11.5 [uninitialized.copy] as indicated:

   >     namespace ranges {
   >       template<input_iterator I, sentinel_for<I> S1,
   >                no-throw-forward-iterator O, no-throw-sentinel<O> S2>
   >           requires constructible_from<iter_value_t<O>, iter_reference_t<I>>
   >         uninitialized_copy_result<I, O>
   >           uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast);
   >       template<input_range IR, no-throw-forward-range OR>
   >           requires constructible_from<range_value_t<OR>, range_reference_t<IR>>
   >         uninitialized_copy_result<safe_iterator_t<IR>, safe_iterator_t<OR>>
   >           uninitialized_copy(IR&& in_range, OR&& out_range);
   >     }

   > > -4- Preconditions: `[ofirst, olast)` shall not overlap with `[ifirst, ilast)`.

   > > -5- Effects: Equivalent to:

   > > >     for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) {
   > > >       ::new (voidify(*ofirst)) remove_reference_t<iter_reference_t<O>>(*ifirst);
   > > >     }
   > > >     return {std::move(ifirst), ofirst};

   > […]

   >     namespace ranges {
   >       template<input_iterator I, no-throw-forward-iterator O, no-throw-sentinel<O> S>
   >           requires constructible_from<iter_value_t<O>, iter_reference_t<I>>
   >         uninitialized_copy_n_result<I, O>
   >           uninitialized_copy_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast);
   >     }

   > > -9- Preconditions: `[ofirst, olast)` shall not overlap with `[ifirst, n)`.

   > > -10- Effects: Equivalent to:

   > > >     auto t = uninitialized_copy(counted_iterator(ifirst, n),
   > > >                                 default_sentinel, ofirst, olast);
   > > >     return {std::move(t.in).base(), t.out};

2. Modify 27.11.6 [uninitialized.move] as indicated:

   >     namespace ranges {
   >       template<input_iterator I, sentinel_for<I> S1,
   >                no-throw-forward-iterator O, no-throw-sentinel<O> S2>
   >           requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
   >         uninitialized_move_result<I, O>
   >           uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast);
   >       template<input_range IR, no-throw-forward-range OR>
   >           requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>>
   >         uninitialized_move_result<safe_iterator_t<IR>, safe_iterator_t<OR>>
   >           uninitialized_move(IR&& in_range, OR&& out_range);
   >     }

   > > -3- Preconditions: `[ofirst, olast)` shall not overlap with `[ifirst, ilast)`.

   > > -4- Effects: Equivalent to:

   > > >     for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) {
   > > >       ::new (voidify(*ofirst))
   > > >         remove_reference_t<iter_reference_t<O>>(ranges::iter_move(*ifirst));
   > > >     }
   > > >     return {std::move(ifirst), ofirst};

   > […]

   >     namespace ranges {
   >       template<input_iterator I, no-throw-forward-iterator O, no-throw-sentinel<O> S>
   >           requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
   >         uninitialized_move_n_result<I, O>
   >           uninitialized_move_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast);
   >     }

   > > -8- Preconditions: `[ofirst, olast)` shall not overlap with `[ifirst, n)`.

   > > -9- Effects: Equivalent to:

   > > >     auto t = uninitialized_move(counted_iterator(ifirst, n),
   > > >                                 default_sentinel, ofirst, olast);
   > > >     return {std::move(t.in).base(), t.out};