23 Iterators library [iterators]

23.5 Iterator adaptors [predef.iterators]

23.5.3 Move iterators and sentinels [move.iterators]

Class template move_­iterator is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator's indirection operator to an rvalue.
Some generic algorithms can be called with move iterators to replace copying with moving.
[Example
:
list<string> s;
// populate the list s
vector<string> v1(s.begin(), s.end());          // copies strings into v1
vector<string> v2(make_move_iterator(s.begin()),
                  make_move_iterator(s.end())); // moves strings into v2
— end example
]

23.5.3.1 Class template move_­iterator [move.iterator]

namespace std {
  template<class Iterator>
  class move_iterator {
  public:
    using iterator_type     = Iterator;
    using iterator_concept  = input_iterator_tag;
    using iterator_category = see below;
    using value_type        = iter_value_t<Iterator>;
    using difference_type   = iter_difference_t<Iterator>;
    using pointer           = Iterator;
    using reference         = iter_rvalue_reference_t<Iterator>;

    constexpr move_iterator();
    constexpr explicit move_iterator(Iterator i);
    template<class U> constexpr move_iterator(const move_iterator<U>& u);
    template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);

    constexpr iterator_type base() const &;
    constexpr iterator_type base() &&;
    constexpr reference operator*() const;

    constexpr move_iterator& operator++();
    constexpr auto operator++(int);
    constexpr move_iterator& operator--();
    constexpr move_iterator operator--(int);

    constexpr move_iterator operator+(difference_type n) const;
    constexpr move_iterator& operator+=(difference_type n);
    constexpr move_iterator operator-(difference_type n) const;
    constexpr move_iterator& operator-=(difference_type n);
    constexpr reference operator[](difference_type n) const;

    template<sentinel_for<Iterator> S>
      friend constexpr bool
        operator==(const move_iterator& x, const move_sentinel<S>& y);
    template<sized_sentinel_for<Iterator> S>
      friend constexpr iter_difference_t<Iterator>
        operator-(const move_sentinel<S>& x, const move_iterator& y);
    template<sized_sentinel_for<Iterator> S>
      friend constexpr iter_difference_t<Iterator>
        operator-(const move_iterator& x, const move_sentinel<S>& y);
    friend constexpr iter_rvalue_reference_t<Iterator>
      iter_move(const move_iterator& i)
        noexcept(noexcept(ranges::iter_move(i.current)));
    template<indirectly_swappable<Iterator> Iterator2>
      friend constexpr void
        iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y)
          noexcept(noexcept(ranges::iter_swap(x.current, y.current)));

  private:
    Iterator current;   // exposition only
  };
}
The member typedef-name iterator_­category denotes
  • random_­access_­iterator_­tag if the type iterator_­traits<​Iterator>​::​iterator_­category models derived_­from<random_­access_­iterator_­tag>, and
  • iterator_­traits<​Iterator>​::​iterator_­category otherwise.

23.5.3.2 Requirements [move.iter.requirements]

The template parameter Iterator shall either meet the Cpp17InputIterator requirements ([input.iterators]) or model input_­iterator ([iterator.concept.input]).
Additionally, if any of the bidirectional traversal functions are instantiated, the template parameter shall either meet the Cpp17BidirectionalIterator requirements ([bidirectional.iterators]) or model bidirectional_­iterator ([iterator.concept.bidir]).
If any of the random access traversal functions are instantiated, the template parameter shall either meet the Cpp17RandomAccessIterator requirements ([random.access.iterators]) or model random_­access_­iterator ([iterator.concept.random.access]).

23.5.3.3 Construction and assignment [move.iter.cons]

constexpr move_iterator();
Effects: Constructs a move_­iterator, value-initializing current.
Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of type Iterator.
constexpr explicit move_iterator(Iterator i);
Effects: Constructs a move_­iterator, initializing current with std​::​move(i).
template<class U> constexpr move_iterator(const move_iterator<U>& u);
Mandates: U is convertible to Iterator.
Effects: Constructs a move_­iterator, initializing current with u.base().
template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);
Mandates: U is convertible to Iterator.
Effects: Assigns u.base() to current.

23.5.3.4 Conversion [move.iter.op.conv]

constexpr Iterator base() const &;
Constraints: Iterator satisfies copy_­constructible.
Preconditions: Iterator models copy_­constructible.
Returns: current.
constexpr Iterator base() &&;
Returns: std​::​move(current).

23.5.3.5 Element access [move.iter.elem]

constexpr reference operator*() const;
Effects: Equivalent to: return ranges​::​iter_­move(current);
constexpr reference operator[](difference_type n) const;
Effects: Equivalent to: ranges​::​iter_­move(current + n);

23.5.3.6 Navigation [move.iter.nav]

constexpr move_iterator& operator++();
Effects: As if by ++current.
Returns: *this.
constexpr auto operator++(int);
Effects: If Iterator models forward_­iterator, equivalent to:
move_iterator tmp = *this;
++current;
return tmp;
Otherwise, equivalent to ++current.
constexpr move_iterator& operator--();
Effects: As if by --current.
Returns: *this.
constexpr move_iterator operator--(int);
Effects: As if by:
move_iterator tmp = *this;
--current;
return tmp;
constexpr move_iterator operator+(difference_type n) const;
Returns: move_­iterator(current + n).
constexpr move_iterator& operator+=(difference_type n);
Effects: As if by: current += n;
Returns: *this.
constexpr move_iterator operator-(difference_type n) const;
Returns: move_­iterator(current - n).
constexpr move_iterator& operator-=(difference_type n);
Effects: As if by: current -= n;
Returns: *this.

23.5.3.7 Comparisons [move.iter.op.comp]

template<class Iterator1, class Iterator2> constexpr bool operator==(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<sentinel_­for<Iterator> S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel<S>& y);
Constraints: x.base() == y.base() is well-formed and convertible to bool.
Returns: x.base() == y.base().
template<class Iterator1, class Iterator2> constexpr bool operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: x.base() < y.base() is well-formed and convertible to bool.
Returns: x.base() < y.base().
template<class Iterator1, class Iterator2> constexpr bool operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: y.base() < x.base() is well-formed and convertible to bool.
Returns: y < x.
template<class Iterator1, class Iterator2> constexpr bool operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: y.base() < x.base() is well-formed and convertible to bool.
Returns: !(y < x).
template<class Iterator1, class Iterator2> constexpr bool operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: x.base() < y.base() is well-formed and convertible to bool.
Returns: !(x < y).
template<class Iterator1, three_­way_­comparable_­with<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Returns: x.base() <=> y.base().

23.5.3.8 Non-member functions [move.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); template<sized_­sentinel_­for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y); template<sized_­sentinel_­for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_iterator& x, const move_sentinel<S>& y);
Returns: x.base() - y.base().
template<class Iterator> constexpr move_iterator<Iterator> operator+(iter_difference_t<Iterator> n, const move_iterator<Iterator>& x);
Constraints: x + n is well-formed and has type Iterator.
Returns: x + n.
friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const move_iterator& i) noexcept(noexcept(ranges::iter_move(i.current)));
Effects: Equivalent to: return ranges​::​iter_­move(i.current);
template<indirectly_­swappable<Iterator> Iterator2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
Effects: Equivalent to: ranges​::​iter_­swap(x.current, y.current).
template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i);
Returns: move_­iterator<Iterator>(std​::​move(i)).

23.5.3.9 Class template move_­sentinel [move.sentinel]

Class template move_­sentinel is a sentinel adaptor useful for denoting ranges together with move_­iterator.
When an input iterator type I and sentinel type S model sentinel_­for<S, I>, move_­sentinel<S> and move_­iterator<I> model sentinel_­for<move_­sentinel<S>, move_­iterator<I>> as well.
[Example
:
A move_­if algorithm is easily implemented with copy_­if using move_­iterator and move_­sentinel:
template<input_iterator I, sentinel_for<I> S, weakly_incrementable O,
         indirect_unary_predicate<I> Pred>
  requires indirectly_movable<I, O>
void move_if(I first, S last, O out, Pred pred) {
  std::ranges::copy_if(move_iterator<I>{first}, move_sentinel<S>{last}, out, pred);
}
— end example
]
namespace std {
  template<semiregular S>
  class move_sentinel {
  public:
    constexpr move_sentinel();
    constexpr explicit move_sentinel(S s);
    template<class S2>
      requires convertible_to<const S2&, S>
        constexpr move_sentinel(const move_sentinel<S2>& s);
    template<class S2>
      requires assignable_from<S&, const S2&>
        constexpr move_sentinel& operator=(const move_sentinel<S2>& s);

    constexpr S base() const;
  private:
    S last;     // exposition only
  };
}

23.5.3.10 Operations [move.sent.ops]

constexpr move_sentinel();
Effects: Value-initializes last.
If is_­trivially_­default_­constructible_­v<S> is true, then this constructor is a constexpr constructor.
constexpr explicit move_sentinel(S s);
Effects: Initializes last with std​::​move(s).
template<class S2> requires convertible_­to<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s);
Effects: Initializes last with s.last.
template<class S2> requires assignable_­from<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s);
Effects: Equivalent to: last = s.last; return *this;
constexpr S base() const;
Returns: last.