9 Iterators library [iterators]

9.7 Iterator adaptors [iterators.predef]

9.7.1 Reverse iterators [iterators.reverse]

Class template reverse_iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence. The fundamental relation between a reverse iterator and its corresponding underlying iterator i is established by the identity: *make_reverse_iterator(i) == *prev(i).

9.7.1.1 Class template reverse_iterator [reverse.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <BidirectionalIterator I>
  class reverse_iterator {
  public:
    using iterator_type = I;
    using difference_type = difference_type_t<I>;
    using value_type = value_type_t<I>;
    using iterator_category = iterator_category_t<I>;
    using reference = reference_t<I>;
    using pointer = I;

    constexpr reverse_iterator();
    explicit constexpr reverse_iterator(I x);
    constexpr reverse_iterator(const reverse_iterator<ConvertibleTo<I>>& i);
    constexpr reverse_iterator& operator=(const reverse_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr reference operator*() const;
    constexpr pointer operator->() const;

    constexpr reverse_iterator& operator++();
    constexpr reverse_iterator  operator++(int);
    constexpr reverse_iterator& operator--();
    constexpr reverse_iterator  operator--(int);

    constexpr reverse_iterator  operator+ (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator  operator- (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr reverse_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reference operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const reverse_iterator& i)
      noexcept(see below);
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
  };

  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const reverse_iterator<I1>& x,
      const reverse_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr reverse_iterator<I> operator+(
      difference_type_t<I> n,
      const reverse_iterator<I>& x);

  template <BidirectionalIterator I>
    constexpr reverse_iterator<I> make_reverse_iterator(I i);
}}}}

9.7.1.2 reverse_iterator operations [reverse.iter.ops]

9.7.1.2.1 reverse_iterator constructor [reverse.iter.cons]

constexpr reverse_iterator();

Effects: Value-initializes 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 I.

explicit constexpr reverse_iterator(I x);

Effects: Initializes current with x.

constexpr reverse_iterator(const reverse_iterator<ConvertibleTo<I>>& i);

Effects: Initializes current with i.current.

9.7.1.2.2 reverse_iterator::operator= [reverse.iter.op=]

constexpr reverse_iterator& operator=(const reverse_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current.

Returns: *this.

9.7.1.2.3 Conversion [reverse.iter.conv]

constexpr I base() const;

Returns: current.

9.7.1.2.4 operator* [reverse.iter.op.star]

constexpr reference operator*() const;

Effects: Equivalent to: return *prev(current);

9.7.1.2.5 operator-> [reverse.iter.opref]

constexpr pointer operator->() const;

Effects: Equivalent to: return prev(current);

9.7.1.2.6 operator++ [reverse.iter.op++]

constexpr reverse_iterator& operator++();

Effects: -- current;

Returns: *this.

constexpr reverse_iterator operator++(int);

Effects:

reverse_iterator tmp = *this;
--current;
return tmp;

9.7.1.2.7 operator-- [reverse.iter.op--]

constexpr reverse_iterator& operator--();

Effects: ++current

Returns: *this.

constexpr reverse_iterator operator--(int);

Effects:

reverse_iterator tmp = *this;
++current;
return tmp;

9.7.1.2.8 operator+ [reverse.iter.op+]

constexpr reverse_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Returns: reverse_iterator(current-n).

9.7.1.2.9 operator+= [reverse.iter.op+=]

constexpr reverse_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Effects: current -= n;

Returns: *this.

9.7.1.2.10 operator- [reverse.iter.op-]

constexpr reverse_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Returns: reverse_iterator(current+n).

9.7.1.2.11 operator-= [reverse.iter.op-=]

constexpr reverse_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Effects: current += n;

Returns: *this.

9.7.1.2.12 operator[] [reverse.iter.opindex]

constexpr reference operator[]( difference_type n) const requires RandomAccessIterator<I>;

Returns: current[-n-1].

9.7.1.2.13 operator== [reverse.iter.op==]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator==( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current == y.current;

9.7.1.2.14 operator!= [reverse.iter.op!=]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator!=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current != y.current;

9.7.1.2.15 operator< [reverse.iter.op<]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current > y.current;

9.7.1.2.16 operator> [reverse.iter.op>]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current < y.current;

9.7.1.2.17 operator>= [reverse.iter.op>=]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current <= y.current;

9.7.1.2.18 operator<= [reverse.iter.op<=]

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<=( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return x.current >= y.current;

9.7.1.2.19 operator- [reverse.iter.opdiff]

template <class I1, class I2> requires SizedSentinel<I1, I2> constexpr difference_type_t<I2> operator-( const reverse_iterator<I1>& x, const reverse_iterator<I2>& y);

Effects: Equivalent to: return y.current - x.current;

9.7.1.2.20 operator+ [reverse.iter.opsum]

template <RandomAccessIterator I> constexpr reverse_iterator<I> operator+( difference_type_t<I> n, const reverse_iterator<I>& x);

Effects: Equivalent to: return reverse_iterator<I>(x.current - n);

9.7.1.2.21 iter_move [reverse.iter.iter_move]

friend constexpr rvalue_reference_t<I> iter_move(const reverse_iterator& i) noexcept(see below);

Effects: Equivalent to: return ranges::iter_move(prev(i.current));

Remarks: The expression in noexcept is equivalent to:

   noexcept(ranges::iter_move(declval<I&>())) && noexcept(--declval<I&>()) &&
     is_nothrow_copy_constructible<I>::value

9.7.1.2.22 iter_swap [reverse.iter.iter_swap]

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to ranges::iter_swap(prev(x.current), prev(y.current)).

Remarks: The expression in noexcept is equivalent to:

  noexcept(ranges::iter_swap(declval<I>(), declval<I>())) && noexcept(--declval<I&>())

9.7.1.2.23 Non-member function make_reverse_iterator() [reverse.iter.make]

template <BidirectionalIterator I> constexpr reverse_iterator<I> make_reverse_iterator(I i);

Returns: reverse_iterator<I>(i).

9.7.2 Insert iterators [iterators.insert]

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, called insert iterators, are provided in the library. With regular iterator classes,

while (first != last) *result++ = *first++;

causes a range [first,last) to be copied into a range starting with result. The same code with result being an insert iterator will insert corresponding elements into the container. This device allows all of the copying algorithms in the library to work in the insert mode instead of the regular overwrite mode.

An insert iterator is constructed from a container and possibly one of its iterators pointing to where insertion takes place if it is neither at the beginning nor at the end of the container. Insert iterators satisfy OutputIterator. operator* returns the insert iterator itself. The assignment operator=(const T& x) is defined on insert iterators to allow writing into them, it inserts x right before where the insert iterator is pointing. In other words, an insert iterator is like a cursor pointing into the container where the insertion takes place. back_insert_iterator inserts elements at the end of a container, front_insert_iterator inserts elements at the beginning of a container, and insert_iterator inserts elements where the iterator points to in a container. back_inserter, front_inserter, and inserter are three functions making the insert iterators out of a container.

9.7.2.1 Class template back_insert_iterator [back.insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class back_insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    constexpr back_insert_iterator();
    explicit back_insert_iterator(Container& x);
    back_insert_iterator&
      operator=(const value_type_t<Container>& value);
    back_insert_iterator&
      operator=(value_type_t<Container>&& value);

    back_insert_iterator& operator*();
    back_insert_iterator& operator++();
    back_insert_iterator operator++(int);

  private:
    Container* container; // exposition only
  };

  template <class Container>
    back_insert_iterator<Container> back_inserter(Container& x);
}}}}

9.7.2.2 back_insert_iterator operations [back.insert.iter.ops]

9.7.2.2.1 back_insert_iterator constructor [back.insert.iter.cons]

constexpr back_insert_iterator();

Effects: Value-initializes container.

explicit back_insert_iterator(Container& x);

Effects: Initializes container with addressof(x).

9.7.2.2.2 back_insert_iterator::operator= [back.insert.iter.op=]

back_insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to container->push_back(value).

Returns: *this.

back_insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to container->push_back(std::move(value)).

Returns: *this.

9.7.2.2.3 back_insert_iterator::operator* [back.insert.iter.op*]

back_insert_iterator& operator*();

Returns: *this.

9.7.2.2.4 back_insert_iterator::operator++ [back.insert.iter.op++]

back_insert_iterator& operator++(); back_insert_iterator operator++(int);

Returns: *this.

9.7.2.2.5 back_inserter [back.inserter]

template <class Container> back_insert_iterator<Container> back_inserter(Container& x);

Returns: back_insert_iterator<Container>(x).

9.7.2.3 Class template front_insert_iterator [front.insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class front_insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    constexpr front_insert_iterator();
    explicit front_insert_iterator(Container& x);
    front_insert_iterator&
      operator=(const value_type_t<Container>& value);
    front_insert_iterator&
      operator=(value_type_t<Container>&& value);

    front_insert_iterator& operator*();
    front_insert_iterator& operator++();
    front_insert_iterator operator++(int);

  private:
    Container* container; // exposition only
  };

  template <class Container>
    front_insert_iterator<Container> front_inserter(Container& x);
}}}}

9.7.2.4 front_insert_iterator operations [front.insert.iter.ops]

9.7.2.4.1 front_insert_iterator constructor [front.insert.iter.cons]

constexpr front_insert_iterator();

Effects: Value-initializes container.

explicit front_insert_iterator(Container& x);

Effects: Initializes container with addressof(x).

9.7.2.4.2 front_insert_iterator::operator= [front.insert.iter.op=]

front_insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to container->push_front(value).

Returns: *this.

front_insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to container->push_front(std::move(value)).

Returns: *this.

9.7.2.4.3 front_insert_iterator::operator* [front.insert.iter.op*]

front_insert_iterator& operator*();

Returns: *this.

9.7.2.4.4 front_insert_iterator::operator++ [front.insert.iter.op++]

front_insert_iterator& operator++(); front_insert_iterator operator++(int);

Returns: *this.

9.7.2.4.5 front_inserter [front.inserter]

template <class Container> front_insert_iterator<Container> front_inserter(Container& x);

Returns: front_insert_iterator<Container>(x).

9.7.2.5 Class template insert_iterator [insert.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <class Container>
  class insert_iterator {
  public:
    using container_type = Container;
    using difference_type = ptrdiff_t;

    insert_iterator();
    insert_iterator(Container& x, iterator_t<Container> i);
    insert_iterator&
      operator=(const value_type_t<Container>& value);
    insert_iterator&
      operator=(value_type_t<Container>&& value);

    insert_iterator& operator*();
    insert_iterator& operator++();
    insert_iterator& operator++(int);

  private:
    Container* container;       // exposition only
    iterator_t<Container> iter; // exposition only
  };

  template <class Container>
    insert_iterator<Container> inserter(Container& x, iterator_t<Container> i);
}}}}

9.7.2.6 insert_iterator operations [insert.iter.ops]

9.7.2.6.1 insert_iterator constructor [insert.iter.cons]

insert_iterator();

Effects: Value-initializes container and iter.

insert_iterator(Container& x, iterator_t<Container> i);

Requires: i is an iterator into x.

Effects: Initializes container with addressof(x) and iter with i.

9.7.2.6.2 insert_iterator::operator= [insert.iter.op=]

insert_iterator& operator=(const value_type_t<Container>& value);

Effects: Equivalent to:

iter = container->insert(iter, value);
++iter;

Returns: *this.

insert_iterator& operator=(value_type_t<Container>&& value);

Effects: Equivalent to:

iter = container->insert(iter, std::move(value));
++iter;

Returns: *this.

9.7.2.6.3 insert_iterator::operator* [insert.iter.op*]

insert_iterator& operator*();

Returns: *this.

9.7.2.6.4 insert_iterator::operator++ [insert.iter.op++]

insert_iterator& operator++(); insert_iterator& operator++(int);

Returns: *this.

9.7.2.6.5 inserter [inserter]

template <class Container> insert_iterator<Container> inserter(Container& x, iterator_t<Container> i);

Returns: insert_iterator<Container>(x, i).

9.7.3 Move iterators and sentinels [iterators.move]

9.7.3.1 Class template move_iterator [move.iterator]

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 of the value type. 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 ]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <InputIterator I>
  class move_iterator {
  public:
    using iterator_type     = I;
    using difference_type   = difference_type_t<I>;
    using value_type        = value_type_t<I>;
    using iterator_category = input_iterator_tag;
    using reference         = rvalue_reference_t<I>;

    constexpr move_iterator();
    explicit constexpr move_iterator(I i);
    constexpr move_iterator(const move_iterator<ConvertibleTo<I>>& i);
    constexpr move_iterator& operator=(const move_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr reference operator*() const;

    constexpr move_iterator& operator++();
    constexpr void operator++(int);
    constexpr move_iterator operator++(int)
      requires ForwardIterator<I>;
    constexpr move_iterator& operator--()
      requires BidirectionalIterator<I>;
    constexpr move_iterator operator--(int)
      requires BidirectionalIterator<I>;

    constexpr move_iterator operator+(difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr move_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr move_iterator operator-(difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr move_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr reference operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const move_iterator& i)
      noexcept(see below);
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const move_iterator& x, const move_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
  };

  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator==(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires EqualityComparableWith<I1, I2>
    constexpr bool operator!=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator<=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>(
      const move_iterator<I1>& x, const move_iterator<I2>& y);
  template <class I1, class I2>
      requires StrictTotallyOrderedWith<I1, I2>
    constexpr bool operator>=(
      const move_iterator<I1>& x, const move_iterator<I2>& y);

  template <class I1, class I2>
      requires SizedSentinel<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const move_iterator<I1>& x,
      const move_iterator<I2>& y);
  template <RandomAccessIterator I>
    constexpr move_iterator<I> operator+(
      difference_type_t<I> n,
      const move_iterator<I>& x);
  template <InputIterator I>
    constexpr move_iterator<I> make_move_iterator(I i);
}}}}

Note: move_iterator does not provide an operator-> because the class member access expression i->m may have different semantics than the expression (*i).m when the expression *i is an rvalue. — end note ]

9.7.3.2 move_iterator operations [move.iter.ops]

9.7.3.2.1 move_iterator constructors [move.iter.op.const]

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 I.

explicit constexpr move_iterator(I i);

Effects: Constructs a move_iterator, initializing current with i.

constexpr move_iterator(const move_iterator<ConvertibleTo<I>>& i);

Effects: Constructs a move_iterator, initializing current with i.current.

9.7.3.2.2 move_iterator::operator= [move.iter.op=]

constexpr move_iterator& operator=(const move_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current.

9.7.3.2.3 move_iterator conversion [move.iter.op.conv]

constexpr I base() const;

Returns: current.

9.7.3.2.4 move_iterator::operator* [move.iter.op.star]

constexpr reference operator*() const;

Effects: Equivalent to: return iter_move(current);

9.7.3.2.5 move_iterator::operator++ [move.iter.op.incr]

constexpr move_iterator& operator++();

Effects: Equivalent to ++current.

Returns: *this.

constexpr void operator++(int);

Effects: Equivalent to ++current.

constexpr move_iterator operator++(int) requires ForwardIterator<I>;

Effects: Equivalent to:

move_iterator tmp = *this;
++current;
return tmp;

9.7.3.2.6 move_iterator::operator-- [move.iter.op.decr]

constexpr move_iterator& operator--() requires BidirectionalIterator<I>;

Effects: Equivalent to --current.

Returns: *this.

constexpr move_iterator operator--(int) requires BidirectionalIterator<I>;

Effects: Equivalent to:

move_iterator tmp = *this;
--current;
return tmp;

9.7.3.2.7 move_iterator::operator+ [move.iter.op.+]

constexpr move_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return move_iterator(current + n);

9.7.3.2.8 move_iterator::operator+= [move.iter.op.+=]

constexpr move_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Effects: Equivalent to current += n.

Returns: *this.

9.7.3.2.9 move_iterator::operator- [move.iter.op.-]

constexpr move_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return move_iterator(current - n);

9.7.3.2.10 move_iterator::operator-= [move.iter.op.-=]

constexpr move_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Effects: Equivalent to current -= n.

Returns: *this.

9.7.3.2.11 move_iterator::operator[] [move.iter.op.index]

constexpr reference operator[](difference_type n) const requires RandomAccessIterator<I>;

Effects: Equivalent to: return iter_move(current + n);

9.7.3.2.12 move_iterator comparisons [move.iter.op.comp]

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator==( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return x.current == y.current;

template <class I1, class I2> requires EqualityComparableWith<I1, I2> constexpr bool operator!=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(x == y);

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return x.current < y.current;

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator<=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(y < x);

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return y < x;

template <class I1, class I2> requires StrictTotallyOrderedWith<I1, I2> constexpr bool operator>=( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return !(x < y);.

9.7.3.2.13 move_iterator non-member functions [move.iter.nonmember]

template <class I1, class I2> requires SizedSentinel<I1, I2> constexpr difference_type_t<I2> operator-( const move_iterator<I1>& x, const move_iterator<I2>& y);

Effects: Equivalent to: return x.current - y.current;

template <RandomAccessIterator I> constexpr move_iterator<I> operator+( difference_type_t<I> n, const move_iterator<I>& x);

Effects: Equivalent to: return x + n;

friend constexpr rvalue_reference_t<I> iter_move(const move_iterator& i) noexcept(see below);

Effects: Equivalent to: return ranges::iter_move(i.current);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.current))

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to: ranges::iter_swap(x.current, y.current).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.current, y.current))

template <InputIterator I> constexpr move_iterator<I> make_move_iterator(I i);

Returns: move_iterator<I>(i).

9.7.3.3 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 satisfy Sentinel<S, I>, Sentinel<move_sentinel<S>, move_iterator<I>> is satisfied as well.

Example: A move_if algorithm is easily implemented with copy_if using move_iterator and move_sentinel:

template <InputIterator I, Sentinel<I> S, WeaklyIncrementable O,
          IndirectUnaryPredicate<I> Pred>
  requires IndirectlyMovable<I, O>
void move_if(I first, S last, O out, Pred pred){
  copy_if(move_iterator<I>{first}, move_sentinel<S>{last}, out, pred);
}

 — end example ]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Semiregular S>
  class move_sentinel {
  public:
    constexpr move_sentinel();
    explicit move_sentinel(S s);
    move_sentinel(const move_sentinel<ConvertibleTo<S>>& s);
    move_sentinel& operator=(const move_sentinel<ConvertibleTo<S>>& s);

    S base() const;

  private:
    S last; // exposition only
  };

  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator==(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_iterator<I>& i, const move_sentinel<S>& s);
  template <class I, Sentinel<I> S>
    constexpr bool operator!=(
      const move_sentinel<S>& s, const move_iterator<I>& i);

  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_sentinel<S>& s, const move_iterator<I>& i);
  template <class I, SizedSentinel<I> S>
    constexpr difference_type_t<I> operator-(
      const move_iterator<I>& i, const move_sentinel<S>& s);

  template <Semiregular S>
    constexpr move_sentinel<S> make_move_sentinel(S s);
}}}}

9.7.3.4 move_sentinel operations [move.sent.ops]

9.7.3.4.1 move_sentinel constructors [move.sent.op.const]

constexpr move_sentinel();

Effects: Constructs a move_sentinel, value-initializing last. If is_trivially_default_constructible<S>::value is true, then this constructor is a constexpr constructor.

explicit move_sentinel(S s);

Effects: Constructs a move_sentinel, initializing last with s.

move_sentinel(const move_sentinel<ConvertibleTo<S>>& s);

Effects: Constructs a move_sentinel, initializing last with s.last.

9.7.3.4.2 move_sentinel::operator= [move.sent.op=]

move_sentinel& operator=(const move_sentinel<ConvertibleTo<S>>& s);

Effects: Assigns s.last to last.

Returns: *this.

9.7.3.4.3 move_sentinel comparisons [move.sent.op.comp]

template <class I, Sentinel<I> S> constexpr bool operator==( const move_iterator<I>& i, const move_sentinel<S>& s); template <class I, Sentinel<I> S> constexpr bool operator==( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return i.current == s.last;

template <class I, Sentinel<I> S> constexpr bool operator!=( const move_iterator<I>& i, const move_sentinel<S>& s); template <class I, Sentinel<I> S> constexpr bool operator!=( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return !(i == s);

9.7.3.4.4 move_sentinel non-member functions [move.sent.nonmember]

template <class I, SizedSentinel<I> S> constexpr difference_type_t<I> operator-( const move_sentinel<S>& s, const move_iterator<I>& i);

Effects: Equivalent to: return s.last - i.current;

template <class I, SizedSentinel<I> S> constexpr difference_type_t<I> operator-( const move_iterator<I>& i, const move_sentinel<S>& s);

Effects: Equivalent to: return i.current - s.last;

template <Semiregular S> constexpr move_sentinel<S> make_move_sentinel(S s);

Returns: move_sentinel<S>(s).

9.7.4 Common iterators [iterators.common]

Class template common_iterator is an iterator/sentinel adaptor that is capable of representing a non-bounded range of elements (where the types of the iterator and sentinel differ) as a bounded range (where they are the same). It does this by holding either an iterator or a sentinel, and implementing the equality comparison operators appropriately.

Note: The common_iterator type is useful for interfacing with legacy code that expects the begin and end of a range to have the same type. — end note ]

Example:

template <class ForwardIterator>
void fun(ForwardIterator begin, ForwardIterator end);

list<int> s;
// populate the list s
using CI =
  common_iterator<counted_iterator<list<int>::iterator>,
                  default_sentinel>;
// call fun on a range of 10 ints
fun(CI(make_counted_iterator(s.begin(), 10)),
    CI(default_sentinel()));

 — end example ]

9.7.4.1 Class template common_iterator [common.iterator]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Iterator I, Sentinel<I> S>
    requires !Same<I, S>
  class common_iterator {
  public:
    using difference_type = difference_type_t<I>;

    constexpr common_iterator();
    constexpr common_iterator(I i);
    constexpr common_iterator(S s);
    constexpr common_iterator(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);
    common_iterator& operator=(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

    decltype(auto) operator*();
    decltype(auto) operator*() const
      requires dereferenceable<const I>;
    decltype(auto) operator->() const
      requires see below;

    common_iterator& operator++();
    decltype(auto) operator++(int);
    common_iterator operator++(int)
      requires ForwardIterator<I>;

    friend rvalue_reference_t<I> iter_move(const common_iterator& i)
      noexcept(see below)
        requires InputIterator<I>;
    template <IndirectlySwappable<I> I2, class S2>
      friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
        noexcept(see below);

  private:
    bool is_sentinel; // exposition only
    I iter;           // exposition only
    S sentinel;       // exposition only
  };

  template <Readable I, class S>
  struct value_type<common_iterator<I, S>> {
    using type = value_type_t<I>;
  };

  template <InputIterator I, class S>
  struct iterator_category<common_iterator<I, S>> {
    using type = input_iterator_tag;
  };

  template <ForwardIterator I, class S>
  struct iterator_category<common_iterator<I, S>> {
    using type = forward_iterator_tag;
  };

  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
    requires EqualityComparableWith<I1, I2>
  bool operator==(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
  template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2>
  bool operator!=(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

  template <class I2, SizedSentinel<I2> I1, SizedSentinel<I2> S1, SizedSentinel<I1> S2>
  difference_type_t<I2> operator-(
    const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);
}}}}

9.7.4.2 common_iterator operations [common.iter.ops]

9.7.4.2.1 common_iterator constructors [common.iter.op.const]

constexpr common_iterator();

Effects: Constructs a common_iterator, value-initializing is_sentinel, iter, and sentinel. 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 I.

constexpr common_iterator(I i);

Effects: Constructs a common_iterator, initializing is_sentinel with false, iter with i, and value-initializing sentinel.

constexpr common_iterator(S s);

Effects: Constructs a common_iterator, initializing is_sentinel with true, value-initializing iter, and initializing sentinel with s.

constexpr common_iterator(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

Effects: Constructs a common_iterator, initializing is_sentinel with u.is_sentinel, iter with u.iter, and sentinel with u.sentinel.

9.7.4.2.2 common_iterator::operator= [common.iter.op=]

common_iterator& operator=(const common_iterator<ConvertibleTo<I>, ConvertibleTo<S>>& u);

Effects: Assigns u.is_sentinel to is_sentinel, u.iter to iter, and u.sentinel to sentinel.

Returns: *this

9.7.4.2.3 common_iterator::operator* [common.iter.op.star]

decltype(auto) operator*(); decltype(auto) operator*() const requires dereferenceable<const I>;

Requires: !is_sentinel

Effects: Equivalent to: return *iter;

9.7.4.2.4 common_iterator::operator-> [common.iter.op.ref]

decltype(auto) operator->() const requires see below;

Requires: !is_sentinel

Effects: Equivalent to:

  • If I is a pointer type or if the expression i.operator->() is well-formed, return iter;

  • Otherwise, if the expression *iter is a glvalue:

    auto&& tmp = *iter;
    return addressof(tmp);
    
  • Otherwise, return proxy(*iter); where proxy is the exposition-only class:

    class proxy {               // exposition only
      value_type_t<I> keep_;
      proxy(reference_t<I>&& x)
        : keep_(std::move(x)) {}
    public:
      const value_type_t<I>* operator->() const {
        return addressof(keep_);
      }
    };
    

The expression in the requires clause is equivalent to:

Readable<const I> &&
  (requires(const I& i) { i.operator->(); } ||
   is_reference<reference_t<I>>::value ||
   Constructible<value_type_t<I>, reference_t<I>>)

9.7.4.2.5 common_iterator::operator++ [common.iter.op.incr]

common_iterator& operator++();

Requires: !is_sentinel

Effects: Equivalent to ++iter.

Returns: *this.

decltype(auto) operator++(int);

Requires: !is_sentinel.

Effects: Equivalent to: return iter++;

common_iterator operator++(int) requires ForwardIterator<I>;

Requires: !is_sentinel

Effects: Equivalent to:

common_iterator tmp = *this;
++iter;
return tmp;

9.7.4.2.6 common_iterator comparisons [common.iter.op.comp]

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> bool operator==( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel || y.iter == x.sentinel) :
    (!y.is_sentinel || x.iter == y.sentinel);

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> requires EqualityComparableWith<I1, I2> bool operator==( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel || y.iter == x.sentinel) :
    (y.is_sentinel ?
        x.iter == y.sentinel :
        x.iter == y.iter);

template <class I1, class I2, Sentinel<I2> S1, Sentinel<I1> S2> bool operator!=( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to: return !(x == y);

template <class I2, SizedSentinel<I2> I1, SizedSentinel<I2> S1, SizedSentinel<I1> S2> difference_type_t<I2> operator-( const common_iterator<I1, S1>& x, const common_iterator<I2, S2>& y);

Effects: Equivalent to:

  return x.is_sentinel ?
    (y.is_sentinel ? 0 : x.sentinel - y.iter) :
    (y.is_sentinel ?
         x.iter - y.sentinel :
         x.iter - y.iter);

9.7.4.2.7 iter_move [common.iter.op.iter_move]

friend rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(see below) requires InputIterator<I>;

Requires: !i.is_sentinel.

Effects: Equivalent to: return ranges::iter_move(i.iter);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.iter))

9.7.4.2.8 iter_swap [common.iter.op.iter_swap]

template <IndirectlySwappable<I> I2> friend void iter_swap(const common_iterator& x, const common_iterator<I2>& y) noexcept(see below);

Requires: !x.is_sentinel && !y.is_sentinel.

Effects: Equivalent to ranges::iter_swap(x.iter, y.iter).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.iter, y.iter))

9.7.5 Default sentinels [default.sentinels]

9.7.5.1 Class default_sentinel [default.sent]

namespace std { namespace experimental { namespace ranges { inline namespace v1 { class default_sentinel { }; }}}}

Class default_sentinel is an empty type used to denote the end of a range. It is intended to be used together with iterator types that know the bound of their range (e.g., counted_iterator ([counted.iterator])).

9.7.6 Counted iterators [iterators.counted]

9.7.6.1 Class template counted_iterator [counted.iterator]

Class template counted_iterator is an iterator adaptor with the same behavior as the underlying iterator except that it keeps track of its distance from its starting position. It can be used together with class default_sentinel in calls to generic algorithms to operate on a range of N elements starting at a given position without needing to know the end position a priori.

Example:

list<string> s;
// populate the list s with at least 10 strings
vector<string> v(make_counted_iterator(s.begin(), 10),
                 default_sentinel()); // copies 10 strings into v

 — end example ]

Two values i1 and i2 of (possibly differing) types counted_iterator<I1> and counted_iterator<I2> refer to elements of the same sequence if and only if next(i1.base(), i1.count()) and next(i2.base(), i2.count()) refer to the same (possibly past-the-end) element.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <Iterator I>
  class counted_iterator {
  public:
    using iterator_type = I;
    using difference_type = difference_type_t<I>;

    constexpr counted_iterator();
    constexpr counted_iterator(I x, difference_type_t<I> n);
    constexpr counted_iterator(const counted_iterator<ConvertibleTo<I>>& i);
    constexpr counted_iterator& operator=(const counted_iterator<ConvertibleTo<I>>& i);

    constexpr I base() const;
    constexpr difference_type_t<I> count() const;
    constexpr decltype(auto) operator*();
    constexpr decltype(auto) operator*() const
      requires dereferenceable<const I>;

    constexpr counted_iterator& operator++();
    decltype(auto) operator++(int);
    constexpr counted_iterator operator++(int)
      requires ForwardIterator<I>;
    constexpr counted_iterator& operator--()
      requires BidirectionalIterator<I>;
    constexpr counted_iterator operator--(int)
      requires BidirectionalIterator<I>;

    constexpr counted_iterator  operator+ (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator+=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr counted_iterator  operator- (difference_type n) const
      requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator-=(difference_type n)
      requires RandomAccessIterator<I>;
    constexpr decltype(auto) operator[](difference_type n) const
      requires RandomAccessIterator<I>;

    friend constexpr rvalue_reference_t<I> iter_move(const counted_iterator& i)
      noexcept(see below)
        requires InputIterator<I>;
    template <IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y)
        noexcept(see below);

  private:
    I current; // exposition only
    difference_type_t<I> cnt; // exposition only
  };

  template <Readable I>
  struct value_type<counted_iterator<I>> {
    using type = value_type_t<I>;
  };

  template <InputIterator I>
  struct iterator_category<counted_iterator<I>> {
    using type = iterator_category_t<I>;
  };

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator==(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
    constexpr bool operator==(
      const counted_iterator<auto>& x, default_sentinel);
    constexpr bool operator==(
      default_sentinel, const counted_iterator<auto>& x);

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator!=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
    constexpr bool operator!=(
      const counted_iterator<auto>& x, default_sentinel y);
    constexpr bool operator!=(
      default_sentinel x, const counted_iterator<auto>& y);

  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator<=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr bool operator>=(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I1, class I2>
      requires Common<I1, I2>
    constexpr difference_type_t<I2> operator-(
      const counted_iterator<I1>& x, const counted_iterator<I2>& y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      const counted_iterator<I>& x, default_sentinel y);
  template <class I>
    constexpr difference_type_t<I> operator-(
      default_sentinel x, const counted_iterator<I>& y);

  template <RandomAccessIterator I>
    constexpr counted_iterator<I> operator+(
      difference_type_t<I> n, const counted_iterator<I>& x);

  template <Iterator I>
    constexpr counted_iterator<I> make_counted_iterator(I i, difference_type_t<I> n);
}}}}

9.7.6.2 counted_iterator operations [counted.iter.ops]

9.7.6.2.1 counted_iterator constructors [counted.iter.op.const]

constexpr counted_iterator();

Effects: Constructs a counted_iterator, value-initializing current and cnt. 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 I.

constexpr counted_iterator(I i, difference_type_t<I> n);

Requires: n >= 0

Effects: Constructs a counted_iterator, initializing current with i and cnt with n.

constexpr counted_iterator(const counted_iterator<ConvertibleTo<I>>& i);

Effects: Constructs a counted_iterator, initializing current with i.current and cnt with i.cnt.

9.7.6.2.2 counted_iterator::operator= [counted.iter.op=]

constexpr counted_iterator& operator=(const counted_iterator<ConvertibleTo<I>>& i);

Effects: Assigns i.current to current and i.cnt to cnt.

9.7.6.2.3 counted_iterator conversion [counted.iter.op.conv]

constexpr I base() const;

Returns: current.

9.7.6.2.4 counted_iterator count [counted.iter.op.cnt]

constexpr difference_type_t<I> count() const;

Returns: cnt.

9.7.6.2.5 counted_iterator::operator* [counted.iter.op.star]

constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>;

Effects: Equivalent to: return *current;

9.7.6.2.6 counted_iterator::operator++ [counted.iter.op.incr]

constexpr counted_iterator& operator++();

Requires: cnt > 0

Effects: Equivalent to:

++current;
--cnt;

Returns: *this.

decltype(auto) operator++(int);

Requires: cnt > 0.

Effects: Equivalent to:

--cnt;
try { return current++; }
catch(...) { ++cnt; throw; }

constexpr counted_iterator operator++(int) requires ForwardIterator<I>;

Requires: cnt > 0

Effects: Equivalent to:

counted_iterator tmp = *this;
++*this;
return tmp;

9.7.6.2.7 counted_iterator::operator-- [counted.iter.op.decr]

constexpr counted_iterator& operator--(); requires BidirectionalIterator<I>

Effects: Equivalent to:

--current;
++cnt;

Returns: *this.

constexpr counted_iterator operator--(int) requires BidirectionalIterator<I>;

Effects: Equivalent to:

counted_iterator tmp = *this;
--*this;
return tmp;

9.7.6.2.8 counted_iterator::operator+ [counted.iter.op.+]

constexpr counted_iterator operator+(difference_type n) const requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects: Equivalent to: return counted_iterator(current + n, cnt - n);

9.7.6.2.9 counted_iterator::operator+= [counted.iter.op.+=]

constexpr counted_iterator& operator+=(difference_type n) requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects:

current += n;
cnt -= n;

Returns: *this.

9.7.6.2.10 counted_iterator::operator- [counted.iter.op.-]

constexpr counted_iterator operator-(difference_type n) const requires RandomAccessIterator<I>;

Requires: -n <= cnt

Effects: Equivalent to: return counted_iterator(current - n, cnt + n);

9.7.6.2.11 counted_iterator::operator-= [counted.iter.op.-=]

constexpr counted_iterator& operator-=(difference_type n) requires RandomAccessIterator<I>;

Requires: -n <= cnt

Effects:

current -= n;
cnt += n;

Returns: *this.

9.7.6.2.12 counted_iterator::operator[] [counted.iter.op.index]

constexpr decltype(auto) operator[](difference_type n) const requires RandomAccessIterator<I>;

Requires: n <= cnt

Effects: Equivalent to: return current[n];

9.7.6.2.13 counted_iterator comparisons [counted.iter.op.comp]

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator==( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return x.cnt == y.cnt;

constexpr bool operator==( const counted_iterator<auto>& x, default_sentinel); constexpr bool operator==( default_sentinel, const counted_iterator<auto>& x);

Effects: Equivalent to: return x.cnt == 0;

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator!=( const counted_iterator<I1>& x, const counted_iterator<I2>& y); constexpr bool operator!=( const counted_iterator<auto>& x, default_sentinel); constexpr bool operator!=( default_sentinel, const counted_iterator<auto>& x);

Requires: For the first overload, x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(x == y);

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator<( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return y.cnt < x.cnt;

Note: The argument order in the Effects element is reversed because cnt counts down, not up.  — end note ]

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator<=( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(y < x);

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator>( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return y < x;

template <class I1, class I2> requires Common<I1, I2> constexpr bool operator>=( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return !(x < y);

9.7.6.2.14 counted_iterator non-member functions [counted.iter.nonmember]

template <class I1, class I2> requires Common<I1, I2> constexpr difference_type_t<I2> operator-( const counted_iterator<I1>& x, const counted_iterator<I2>& y);

Requires: x and y shall refer to elements of the same sequence ([iterators.counted]).

Effects: Equivalent to: return y.cnt - x.cnt;

template <class I> constexpr difference_type_t<I> operator-( const counted_iterator<I>& x, default_sentinel y);

Effects: Equivalent to: return -x.cnt;

template <class I> constexpr difference_type_t<I> operator-( default_sentinel x, const counted_iterator<I>& y);

Effects: Equivalent to: return y.cnt;

template <RandomAccessIterator I> constexpr counted_iterator<I> operator+( difference_type_t<I> n, const counted_iterator<I>& x);

Requires: n <= x.cnt.

Effects: Equivalent to: return x + n;

friend constexpr rvalue_reference_t<I> iter_move(const counted_iterator& i) noexcept(see below) requires InputIterator<I>;

Effects: Equivalent to: return ranges::iter_move(i.current);

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_move(i.current))

template <IndirectlySwappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(see below);

Effects: Equivalent to ranges::iter_swap(x.current, y.current).

Remarks: The expression in noexcept is equivalent to:

noexcept(ranges::iter_swap(x.current, y.current))

template <Iterator I> constexpr counted_iterator<I> make_counted_iterator(I i, difference_type_t<I> n);

Requires: n >= 0.

Returns: counted_iterator<I>(i, n).

9.7.7 Dangling wrapper [dangling.wrappers]

9.7.7.1 Class template dangling [dangling.wrap]

Class template dangling is a wrapper for an object that refers to another object whose lifetime may have ended. It is used by algorithms that accept rvalue ranges and return iterators.

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  template <CopyConstructible T>
  class dangling {
  public:
    constexpr dangling() requires DefaultConstructible<T>;
    constexpr dangling(T t);
    constexpr T get_unsafe() const;
  private:
    T value; // exposition only
  };

  template <Range R>
  using safe_iterator_t =
    conditional_t<is_lvalue_reference<R>::value,
      iterator_t<R>,
      dangling<iterator_t<R>>>;
}}}}

9.7.7.2 dangling operations [dangling.wrap.ops]

9.7.7.2.1 dangling constructors [dangling.wrap.op.const]

constexpr dangling() requires DefaultConstructible<T>;

Effects: Constructs a dangling, value-initializing value.

constexpr dangling(T t);

Effects: Constructs a dangling, initializing value with t.

9.7.7.2.2 dangling::get_unsafe [dangling.wrap.op.get]

constexpr T get_unsafe() const;

Returns: value.

9.7.8 Unreachable sentinel [unreachable.sentinels]

9.7.8.1 Class unreachable [unreachable.sentinel]

Class unreachable is a sentinel type that can be used with any Iterator to denote an infinite range. Comparing an iterator for equality with an object of type unreachable always returns false.

Example:

char* p;
// set p to point to a character buffer containing newlines
char* nl = find(p, unreachable(), '\n');

Provided a newline character really exists in the buffer, the use of unreachable above potentially makes the call to find more efficient since the loop test against the sentinel does not require a conditional branch.  — end example ]

namespace std { namespace experimental { namespace ranges { inline namespace v1 {
  class unreachable { };

  template <Iterator I>
    constexpr bool operator==(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator==(unreachable, const I&) noexcept;
  template <Iterator I>
    constexpr bool operator!=(const I&, unreachable) noexcept;
  template <Iterator I>
    constexpr bool operator!=(unreachable, const I&) noexcept;
}}}}

9.7.8.2 unreachable operations [unreachable.sentinel.ops]

9.7.8.2.1 operator== [unreachable.sentinel.op==]

template <Iterator I> constexpr bool operator==(const I&, unreachable) noexcept; template <Iterator I> constexpr bool operator==(unreachable, const I&) noexcept;

Returns: false.

9.7.8.2.2 operator!= [unreachable.sentinel.op!=]

template <Iterator I> constexpr bool operator!=(const I& x, unreachable y) noexcept; template <Iterator I> constexpr bool operator!=(unreachable x, const I& y) noexcept;

Returns: true.