25 Iterators library [iterators]

25.5 Iterator adaptors [predef.iterators]

25.5.7 Counted iterators [iterators.counted] 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 1: 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 there exists some integer n such that next(i1.base(), i1.count() + n) and next(i2.base(), i2.count() + n) refer to the same (possibly past-the-end) element.
namespace std { template<input_­or_­output_­iterator I> class counted_iterator { public: using iterator_type = I; using value_type = iter_value_t<I>; // present only // if I models indirectly_­readable using difference_type = iter_difference_t<I>; using iterator_concept = typename I::iterator_concept; // present only // if the qualified-id I​::​iterator_­concept is valid and denotes a type using iterator_category = typename I::iterator_category; // present only // if the qualified-id I​::​iterator_­category is valid and denotes a type constexpr counted_iterator() requires default_­initializable<I> = default; constexpr counted_iterator(I x, iter_difference_t<I> n); template<class I2> requires convertible_­to<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x); template<class I2> requires assignable_­from<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x); constexpr const I& base() const & noexcept; constexpr I base() &&; constexpr iter_difference_t<I> count() const noexcept; constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>; constexpr auto operator->() const noexcept requires contiguous_­iterator<I>; constexpr counted_iterator& operator++(); constexpr decltype(auto) operator++(int); constexpr counted_iterator operator++(int) requires forward_­iterator<I>; constexpr counted_iterator& operator--() requires bidirectional_­iterator<I>; constexpr counted_iterator operator--(int) requires bidirectional_­iterator<I>; constexpr counted_iterator operator+(iter_difference_t<I> n) const requires random_­access_­iterator<I>; friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires random_­access_­iterator<I>; constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires random_­access_­iterator<I>; constexpr counted_iterator operator-(iter_difference_t<I> n) const requires random_­access_­iterator<I>; template<common_­with<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 random_­access_­iterator<I>; constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires random_­access_­iterator<I>; template<common_­with<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); template<common_­with<I> I2> friend constexpr strong_ordering 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 input_­iterator<I>; template<indirectly_­swappable<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<input_­iterator I> requires same_­as<ITER_TRAITS(I), iterator_traits<I>> // see [iterator.concepts.general] struct iterator_traits<counted_iterator<I>> : iterator_traits<I> { using pointer = conditional_t<contiguous_­iterator<I>, add_pointer_t<iter_reference_t<I>>, void>; }; }