22 Iterators library [iterators]

22.5 Iterator adaptors [predef.iterators]

22.5.6 Counted iterators [iterators.counted]

22.5.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 the distance to the end of its range.
It can be used together with 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;
// copies 10 strings into v:
ranges::copy(counted_iterator(s.begin(), 10), default_sentinel, back_inserter(v));
end example
]
Two values i1 and i2 of 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 {
  template<Iterator I>
  class counted_iterator {
  public:
    using iterator_type = I;

    constexpr counted_iterator() = default;
    constexpr counted_iterator(I x, iter_difference_t<I> n);
    template<class I2>
      requires ConvertibleTo<const I2&, I>
        constexpr counted_iterator(const counted_iterator<I2>& x);

    template<class I2>
      requires Assignable<I&, const I2&>
        constexpr counted_iterator& operator=(const counted_iterator<I2>& x);

    constexpr I base() const;
    constexpr iter_difference_t<I> count() const noexcept;
    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+(iter_difference_t<I> n) const
      requires RandomAccessIterator<I>;
    friend constexpr counted_iterator operator+(
      iter_difference_t<I> n, const counted_iterator& x)
        requires RandomAccessIterator<I>;
    constexpr counted_iterator& operator+=(iter_difference_t<I> n)
      requires RandomAccessIterator<I>;

    constexpr counted_iterator operator-(iter_difference_t<I> n) const
      requires RandomAccessIterator<I>;
    template<Common<I> I2>
      friend constexpr iter_difference_t<I2> operator-(
        const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr iter_difference_t<I> operator-(
      const counted_iterator& x, default_sentinel_t);
    friend constexpr iter_difference_t<I> operator-(
      default_sentinel_t, const counted_iterator& y);
    constexpr counted_iterator& operator-=(iter_difference_t<I> n)
      requires RandomAccessIterator<I>;

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

    template<Common<I> I2>
      friend constexpr bool operator==(
        const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr bool operator==(
      const counted_iterator& x, default_sentinel_t);
    friend constexpr bool operator==(
      default_sentinel_t, const counted_iterator& x);

    template<Common<I> I2>
      friend constexpr bool operator!=(
        const counted_iterator& x, const counted_iterator<I2>& y);
    friend constexpr bool operator!=(
      const counted_iterator& x, default_sentinel_t y);
    friend constexpr bool operator!=(
      default_sentinel_t x, const counted_iterator& y);

    template<Common<I> I2>
      friend constexpr bool operator<(
        const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
      friend constexpr bool operator>(
        const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
      friend constexpr bool operator<=(
        const counted_iterator& x, const counted_iterator<I2>& y);
    template<Common<I> I2>
      friend constexpr bool operator>=(
        const counted_iterator& x, const counted_iterator<I2>& y);

    friend constexpr iter_rvalue_reference_t<I> iter_move(const counted_iterator& i)
      noexcept(noexcept(ranges::iter_move(i.current)))
        requires InputIterator<I>;
    template<IndirectlySwappable<I> I2>
      friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y)
        noexcept(noexcept(ranges::iter_swap(x.current, y.current)));

  private:
    I current = I();                    // exposition only
    iter_difference_t<I> length = 0;    // exposition only
  };

  template<class I>
  struct incrementable_traits<counted_iterator<I>> {
    using difference_type = iter_difference_t<I>;
  };

  template<InputIterator I>
  struct iterator_traits<counted_iterator<I>> : iterator_traits<I> {
    using pointer = void;
  };
}

22.5.6.2 Constructors and conversions [counted.iter.const]

constexpr counted_iterator(I i, iter_difference_t<I> n);
Expects: n >= 0.
Effects: Initializes current with i and length with n.
template<class I2> requires ConvertibleTo<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x);
Effects: Initializes current with x.current and length with x.length.
template<class I2> requires Assignable<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x);
Effects: Assigns x.current to current and x.length to length.
Returns: *this.

22.5.6.3 Accessors [counted.iter.access]

constexpr I base() const;
Effects: Equivalent to: return current;
constexpr iter_difference_t<I> count() const noexcept;
Effects: Equivalent to: return length;

22.5.6.4 Element access [counted.iter.elem]

constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>;
Effects: Equivalent to: return *current;
constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires RandomAccessIterator<I>;
Expects: n < length.
Effects: Equivalent to: return current[n];

22.5.6.5 Navigation [counted.iter.nav]

constexpr counted_iterator& operator++();
Expects: length > 0.
Effects: Equivalent to:
++current;
--length;
return *this;
decltype(auto) operator++(int);
Expects: length > 0.
Effects: Equivalent to:
--length;
try { return current++; }
catch(...) { ++length; throw; }
constexpr counted_iterator operator++(int) requires ForwardIterator<I>;
Effects: Equivalent to:
counted_iterator tmp = *this;
++*this;
return tmp;
constexpr counted_iterator& operator--(); requires BidirectionalIterator<I>
Effects: Equivalent to:
--current;
++length;
return *this;
constexpr counted_iterator operator--(int) requires BidirectionalIterator<I>;
Effects: Equivalent to:
counted_iterator tmp = *this;
--*this;
return tmp;
constexpr counted_iterator operator+(iter_difference_t<I> n) const requires RandomAccessIterator<I>;
Effects: Equivalent to: return counted_­iterator(current + n, length - n);
friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires RandomAccessIterator<I>;
Effects: Equivalent to: return x + n;
constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires RandomAccessIterator<I>;
Expects: n <= length.
Effects: Equivalent to:
current += n;
length -= n;
return *this;
constexpr counted_iterator operator-(iter_difference_t<I> n) const requires RandomAccessIterator<I>;
Effects: Equivalent to: return counted_­iterator(current - n, length + n);
template<Common<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y);
Expects: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return y.length - x.length;
friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t);
Effects: Equivalent to: return -x.length;
friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y);
Effects: Equivalent to: return y.length;
constexpr counted_iterator& operator-=(iter_difference_t<I> n) requires RandomAccessIterator<I>;
Expects: -n <= length.
Effects: Equivalent to:
current -= n;
length += n;
return *this;

22.5.6.6 Comparisons [counted.iter.cmp]

template<Common<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y);
Expects: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return x.length == y.length;
friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t); friend constexpr bool operator==( default_sentinel_t, const counted_iterator& x);
Effects: Equivalent to: return x.length == 0;
template<Common<I> I2> friend constexpr bool operator!=( const counted_iterator& x, const counted_iterator<I2>& y); friend constexpr bool operator!=( const counted_iterator& x, default_sentinel_t y); friend constexpr bool operator!=( default_sentinel_t x, const counted_iterator& y);
Effects: Equivalent to: return !(x == y);
template<Common<I> I2> friend constexpr bool operator<( const counted_iterator& x, const counted_iterator<I2>& y);
Expects: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return y.length < x.length;
[Note
:
The argument order in the Effects: element is reversed because length counts down, not up.
end note
]
template<Common<I> I2> friend constexpr bool operator>( const counted_iterator& x, const counted_iterator<I2>& y);
Effects: Equivalent to: return y < x;
template<Common<I> I2> friend constexpr bool operator<=( const counted_iterator& x, const counted_iterator<I2>& y);
Effects: Equivalent to: return !(y < x);
template<Common<I> I2> friend constexpr bool operator>=( const counted_iterator& x, const counted_iterator<I2>& y);
Effects: Equivalent to: return !(x < y);

22.5.6.7 Customizations [counted.iter.cust]

friend constexpr iter_rvalue_reference_t<I> iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires InputIterator<I>;
Effects: Equivalent to: return ranges::iter_­move(i.current);
template<IndirectlySwappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
Effects: Equivalent to ranges::iter_­swap(x.current, y.current).