25 Ranges library [ranges]

25.7 Range adaptors [range.adaptors]

25.7.24 Enumerate view [range.enumerate]

25.7.24.1 Overview [range.enumerate.overview]

enumerate_view is a view whose elements represent both the position and value from a sequence of elements.
The name views​::​enumerate denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​enumerate(E) is expression-equivalent to enumerate_view<views​::​all_t<decltype((E))>>(E).
[Example 1: vector<int> vec{ 1, 2, 3 }; for (auto [index, value] : views::enumerate(vec)) cout << index << ":" << value << ' '; // prints 0:1 1:2 2:3 — end example]

25.7.24.2 Class template enumerate_view [range.enumerate.view]

namespace std::ranges { template<view V> requires range-with-movable-references<V> class enumerate_view : public view_interface<enumerate_view<V>> { V base_ = V(); // exposition only // [range.enumerate.iterator], class template enumerate_view​::​iterator template<bool Const> class iterator; // exposition only // [range.enumerate.sentinel], class template enumerate_view​::​sentinel template<bool Const> class sentinel; // exposition only public: constexpr enumerate_view() requires default_initializable<V> = default; constexpr explicit enumerate_view(V base); constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(ranges::begin(base_), 0); } constexpr auto begin() const requires range-with-movable-references<const V> { return iterator<true>(ranges::begin(base_), 0); } constexpr auto end() requires (!simple-view<V>) { if constexpr (forward_range<V> && common_range<V> && sized_range<V>) return iterator<false>(ranges::end(base_), ranges::distance(base_)); else return sentinel<false>(ranges::end(base_)); } constexpr auto end() const requires range-with-movable-references<const V> { if constexpr (forward_range<const V> && common_range<const V> && sized_range<const V>) return iterator<true>(ranges::end(base_), ranges::distance(base_)); else return sentinel<true>(ranges::end(base_)); } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } }; template<class R> enumerate_view(R&&) -> enumerate_view<views::all_t<R>>; }
constexpr explicit enumerate_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.24.3 Class template enumerate_view​::​iterator [range.enumerate.iterator]

namespace std::ranges { template<view V> requires range-with-movable-references<V> template<bool Const> class enumerate_view<V>::iterator { using Base = maybe-const<Const, V>; // exposition only public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using difference_type = range_difference_t<Base>; using value_type = tuple<difference_type, range_value_t<Base>>; private: using reference-type = // exposition only tuple<difference_type, range_reference_t<Base>>; iterator_t<Base> current_ = iterator_t<Base>(); // exposition only difference_type pos_ = 0; // exposition only constexpr explicit iterator(iterator_t<Base> current, difference_type pos); // exposition only public: iterator() requires default_initializable<iterator_t<Base>> = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr const iterator_t<Base>& base() const & noexcept; constexpr iterator_t<Base> base() &&; constexpr difference_type index() const noexcept; constexpr auto operator*() const { return reference-type(pos_, *current_); } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr auto operator[](difference_type n) const requires random_access_range<Base> { return reference-type(pos_ + n, current_[n]); } friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept; friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept; friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept; friend constexpr auto iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)) && is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) { return tuple<difference_type, range_rvalue_reference_t<Base>>(i.pos_, ranges::iter_move(i.current_)); } }; }
The member typedef-name iterator​::​iterator_concept is defined as follows:
constexpr explicit iterator(iterator_t<Base> current, difference_type pos);
Effects: Initializes current_ with std​::​move(current) and pos_ with pos.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_) and pos_ with i.pos_.
constexpr const iterator_t<Base>& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr iterator_t<Base> base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr difference_type index() const noexcept;
Effects: Equivalent to: return pos_;
constexpr iterator& operator++();
Effects: Equivalent to: ++current_; ++pos_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto temp = *this; ++*this; return temp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --current_; --pos_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto temp = *this; --*this; return temp;
constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ += n; pos_ += n; return *this;
constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ -= n; pos_ -= n; return *this;
friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ == y.pos_;
friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ <=> y.pos_;
friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: auto temp = x; temp += y; return temp;
friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y + x;
friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: auto temp = x; temp -= y; return temp;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ - y.pos_;

25.7.24.4 Class template enumerate_view​::​sentinel [range.enumerate.sentinel]

namespace std::ranges { template<view V> requires range-with-movable-references<V> template<bool Const> class enumerate_view<V>::sentinel { using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only constexpr explicit sentinel(sentinel_t<Base> end); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with std​::​move(end).
constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(other.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ == y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ - y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y);
Effects: Equivalent to: return x.end_ - y.current_;