[predef.iterators] (original) (raw)

24 Iterators library [iterators]

24.5 Iterator adaptors [predef.iterators]


24.5.1 Reverse iterators [reverse.iterators]

24.5.1.1 General [reverse.iterators.general]

24.5.1.2 Class template reverse_iterator [reverse.iterator]

24.5.1.3 Requirements [reverse.iter.requirements]

24.5.1.4 Construction and assignment [reverse.iter.cons]

24.5.1.5 Conversion [reverse.iter.conv]

24.5.1.6 Element access [reverse.iter.elem]

24.5.1.7 Navigation [reverse.iter.nav]

24.5.1.8 Comparisons [reverse.iter.cmp]

24.5.1.9 Non-member functions [reverse.iter.nonmember]

24.5.2 Insert iterators [insert.iterators]

24.5.2.1 General [insert.iterators.general]

24.5.2.2 Class template back_insert_iterator [back.insert.iterator]

24.5.2.2.1 General [back.insert.iter.general]

24.5.2.2.2 Operations [back.insert.iter.ops]

24.5.2.2.3 back_inserter [back.inserter]

24.5.2.3 Class template front_insert_iterator [front.insert.iterator]

24.5.2.3.1 General [front.insert.iter.general]

24.5.2.3.2 Operations [front.insert.iter.ops]

24.5.2.3.3 front_inserter [front.inserter]

24.5.2.4 Class template insert_iterator [insert.iterator]

24.5.2.4.1 General [insert.iter.general]

24.5.2.4.2 Operations [insert.iter.ops]

24.5.2.4.3 inserter [inserter]

24.5.3 Constant iterators and sentinels [const.iterators]

24.5.3.1 General [const.iterators.general]

24.5.3.2 Alias templates [const.iterators.alias]

24.5.3.3 Class template basic_const_iterator [const.iterators.iterator]

24.5.3.4 Member types [const.iterators.types]

24.5.3.5 Operations [const.iterators.ops]

24.5.4 Move iterators and sentinels [move.iterators]

24.5.4.1 General [move.iterators.general]

24.5.4.2 Class template move_iterator [move.iterator]

24.5.4.3 Requirements [move.iter.requirements]

24.5.4.4 Construction and assignment [move.iter.cons]

24.5.4.5 Conversion [move.iter.op.conv]

24.5.4.6 Element access [move.iter.elem]

24.5.4.7 Navigation [move.iter.nav]

24.5.4.8 Comparisons [move.iter.op.comp]

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

24.5.4.10 Class template move_sentinel [move.sentinel]

24.5.4.11 Operations [move.sent.ops]

24.5.5 Common iterators [iterators.common]

24.5.5.1 Class template common_iterator [common.iterator]

24.5.5.2 Associated types [common.iter.types]

24.5.5.3 Constructors and conversions [common.iter.const]

24.5.5.4 Accessors [common.iter.access]

24.5.5.5 Navigation [common.iter.nav]

24.5.5.6 Comparisons [common.iter.cmp]

24.5.5.7 Customizations [common.iter.cust]

24.5.6 Default sentinel [default.sentinel]

24.5.7 Counted iterators [iterators.counted]

24.5.7.1 Class template counted_iterator [counted.iterator]

24.5.7.2 Constructors and conversions [counted.iter.const]

24.5.7.3 Accessors [counted.iter.access]

24.5.7.4 Element access [counted.iter.elem]

24.5.7.5 Navigation [counted.iter.nav]

24.5.7.6 Comparisons [counted.iter.cmp]

24.5.7.7 Customizations [counted.iter.cust]

24.5.8 Unreachable sentinel [unreachable.sentinel]


24.5.1 Reverse iterators [reverse.iterators]

24.5.1.1 General [reverse.iterators.general]

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.

24.5.1.2 Class template reverse_iterator [reverse.iterator]

namespace std { template<class Iterator> class reverse_iterator { public: using iterator_type = Iterator;using iterator_concept = see below;using iterator_category = see below;using value_type = iter_value_t<Iterator>;using difference_type = iter_difference_t<Iterator>;using pointer = iterator_traits<Iterator>::pointer;using reference = iter_reference_t<Iterator>;constexpr reverse_iterator();constexpr explicit reverse_iterator(Iterator x);template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);constexpr Iterator base() const;constexpr reference operator*() const;constexpr pointer operator->() const requires see below;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;constexpr reverse_iterator& operator+=(difference_type n);constexpr reverse_iterator operator- (difference_type n) const;constexpr reverse_iterator& operator-=(difference_type n);constexpr unspecified operator[](difference_type n) const;friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(see below);template<indirectly_swappable<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x,const reverse_iterator<Iterator2>& y) noexcept(see below);protected: Iterator current;};}

The member typedef-name iterator_category denotes

24.5.1.3 Requirements [reverse.iter.requirements]

Additionally,Iteratorshall either meet the requirements of a_Cpp17RandomAccessIterator_ ([random.access.iterators]) or modelrandom_access_iterator ([iterator.concept.random.access]) if the definitions of any of the members

or the non-member operators ([reverse.iter.cmp])

are instantiated ([temp.inst]).

24.5.1.4 Construction and assignment [reverse.iter.cons]

constexpr reverse_iterator();

Effects: Value-initializescurrent.

constexpr explicit reverse_iterator(Iterator x);

Effects: Initializescurrentwith x.

template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);

Constraints: is_same_v<U, Iterator> is false andconst U& models convertible_to<Iterator>.

Effects: Initializescurrentwithu.current.

template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);

Effects: Assigns u.current to current.

24.5.1.5 Conversion [reverse.iter.conv]

constexpr Iterator base() const;

24.5.1.6 Element access [reverse.iter.elem]

constexpr reference operator*() const;

Effects: As if by:Iterator tmp = current;return *--tmp;

constexpr pointer operator->() const requires (is_pointer_v<Iterator> || requires(const Iterator i) { i.operator->(); });

Effects:

constexpr _unspecified_ operator[](difference_type n) const;

Returns: current[-n - 1].

24.5.1.7 Navigation [reverse.iter.nav]

constexpr reverse_iterator operator+(difference_type n) const;

Returns: reverse_iterator(current - n).

constexpr reverse_iterator operator-(difference_type n) const;

Returns: reverse_iterator(current + n).

constexpr reverse_iterator& operator++();

Effects: As if by: --current;

constexpr reverse_iterator operator++(int);

Effects: As if by:reverse_iterator tmp = *this;--current;return tmp;

constexpr reverse_iterator& operator--();

Effects: As if by ++current.

constexpr reverse_iterator operator--(int);

Effects: As if by:reverse_iterator tmp = *this;++current;return tmp;

constexpr reverse_iterator& operator+=(difference_type n);

Effects: As if by: current -= n;

constexpr reverse_iterator& operator-=(difference_type n);

Effects: As if by: current += n;

24.5.1.8 Comparisons [reverse.iter.cmp]

template<class Iterator1, class Iterator2> constexpr bool operator==( const reverse_iterator<Iterator1>& x,const reverse_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 reverse_iterator<Iterator1>& x,const reverse_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 reverse_iterator<Iterator1>& x,const reverse_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 reverse_iterator<Iterator1>& x,const reverse_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 reverse_iterator<Iterator1>& x,const reverse_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 reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Constraints: x.base() <= y.base() is well-formed and convertible to bool.

Returns: x.base() <= y.base().

template<class Iterator1, [three_way_comparable_with](cmp.concept#concept:three%5Fway%5Fcomparable%5Fwith "17.12.4 Concept three_­way_­comparable [cmp.concept]")<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y);

Returns: y.base() <=> x.base().

[Note 1:

The argument order in the Returns: element is reversed because this is a reverse iterator.

— _end note_]

24.5.1.9 Non-member functions [reverse.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const reverse_iterator<Iterator1>& x,const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());

Returns: y.base() - x.base().

template<class Iterator> constexpr reverse_iterator<Iterator> operator+( iter_difference_t<Iterator> n,const reverse_iterator<Iterator>& x);

Returns: reverse_iterator<Iterator>(x.base() - n).

friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(_see below_);

Effects: Equivalent to:auto tmp = i.base();return ranges::iter_move(--tmp);

Remarks: The exception specification is equivalent to:is_nothrow_copy_constructible_v<Iterator> && noexcept(ranges::iter_move(--declval<Iterator&>()))

template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x,const reverse_iterator<Iterator2>& y) noexcept(_see below_);

Effects: Equivalent to:auto xtmp = x.base();auto ytmp = y.base(); ranges::iter_swap(--xtmp, --ytmp);

Remarks: The exception specification is equivalent to:is_nothrow_copy_constructible_v<Iterator> &&is_nothrow_copy_constructible_v<Iterator2> && noexcept(ranges::iter_swap(--declval<Iterator&>(), --declval<Iterator2&>()))

template<class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);

Returns: reverse_iterator<Iterator>(i).

24.5.2 Insert iterators [insert.iterators]

24.5.2.1 General [insert.iterators.general]

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, calledinsert 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 withresultbeing an insert iterator will insert corresponding elements into the container.

This device allows all of the copying algorithms in the library to work in theinsert modeinstead 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 meet the requirements of output iterators.

operator*returns the insert iterator itself.

The assignmentoperator=(const T& x)is defined on insert iterators to allow writing into them, it insertsxright 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_iteratorinserts elements at the end of a container,front_insert_iteratorinserts elements at the beginning of a container, andinsert_iteratorinserts elements where the iterator points to in a container.

back_inserter,front_inserter, andinserterare three functions making the insert iterators out of a container.

24.5.2.2 Class template back_insert_iterator [back.insert.iterator]

24.5.2.2.1 General [back.insert.iter.general]

namespace std { template<class Container> class back_insert_iterator { protected: Container* container;public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container;constexpr explicit back_insert_iterator(Container& x);constexpr back_insert_iterator& operator=(const typename Container::value_type& value);constexpr back_insert_iterator& operator=(typename Container::value_type&& value);constexpr back_insert_iterator& operator*();constexpr back_insert_iterator& operator++();constexpr back_insert_iterator operator++(int);};}

24.5.2.2.2 Operations [back.insert.iter.ops]

constexpr explicit back_insert_iterator(Container& x);

Effects: Initializescontainerwith addressof(x).

constexpr back_insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by: container->push_back(value);

constexpr back_insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by: container->push_back(std​::​move(value));

constexpr back_insert_iterator& operator*();

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

24.5.2.2.3 back_inserter [back.inserter]

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

Returns: back_insert_iterator<Container>(x).

24.5.2.3 Class template front_insert_iterator [front.insert.iterator]

24.5.2.3.1 General [front.insert.iter.general]

namespace std { template<class Container> class front_insert_iterator { protected: Container* container;public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container;constexpr explicit front_insert_iterator(Container& x);constexpr front_insert_iterator& operator=(const typename Container::value_type& value);constexpr front_insert_iterator& operator=(typename Container::value_type&& value);constexpr front_insert_iterator& operator*();constexpr front_insert_iterator& operator++();constexpr front_insert_iterator operator++(int);};}

24.5.2.3.2 Operations [front.insert.iter.ops]

constexpr explicit front_insert_iterator(Container& x);

Effects: Initializescontainerwith addressof(x).

constexpr front_insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by: container->push_front(value);

constexpr front_insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by: container->push_front(std​::​move(value));

constexpr front_insert_iterator& operator*();

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

24.5.2.3.3 front_inserter [front.inserter]

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

Returns: front_insert_iterator<Container>(x).

24.5.2.4 Class template insert_iterator [insert.iterator]

24.5.2.4.1 General [insert.iter.general]

namespace std { template<class Container> class insert_iterator { protected: Container* container; ranges::iterator_t<Container> iter;public: using iterator_category = output_iterator_tag;using value_type = void;using difference_type = ptrdiff_t;using pointer = void;using reference = void;using container_type = Container;constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i);constexpr insert_iterator& operator=(const typename Container::value_type& value);constexpr insert_iterator& operator=(typename Container::value_type&& value);constexpr insert_iterator& operator*();constexpr insert_iterator& operator++();constexpr insert_iterator& operator++(int);};}

24.5.2.4.2 Operations [insert.iter.ops]

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

Effects: Initializescontainerwith addressof(x) anditerwith i.

constexpr insert_iterator& operator=(const typename Container::value_type& value);

Effects: As if by:iter = container->insert(iter, value);++iter;

constexpr insert_iterator& operator=(typename Container::value_type&& value);

Effects: As if by:iter = container->insert(iter, std::move(value));++iter;

constexpr insert_iterator& operator*();

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

24.5.2.4.3 inserter [inserter]

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

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

24.5.3 Constant iterators and sentinels [const.iterators]

24.5.3.1 General [const.iterators.general]

Class template basic_const_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 a type such that the adapted iterator is a constant iterator ([iterator.requirements]).

Some generic algorithms can be called with constant iterators to avoid mutation.

Specializations of basic_const_iterator are constant iterators.

24.5.3.2 Alias templates [const.iterators.alias]

Result: If I models constant-iterator, I.

Otherwise, basic_const_iterator<I>.

24.5.3.3 Class template basic_const_iterator [const.iterators.iterator]

namespace std { template<class I> concept not-a-const-iterator = see below; template<indirectly_readable I> using iter-const-rvalue-reference-t = common_reference_t<const iter_value_t<I>&&, iter_rvalue_reference_t<I>>;template<input_iterator Iterator> class basic_const_iterator { Iterator current_ = Iterator(); using reference = iter_const_reference_t<Iterator>; using rvalue-reference = iter-const-rvalue-reference-t<Iterator>;public: using iterator_concept = see below;using iterator_category = see below; using value_type = iter_value_t<Iterator>;using difference_type = iter_difference_t<Iterator>; basic_const_iterator() requires default_initializable<Iterator> = default;constexpr basic_const_iterator(Iterator current);template<convertible_to<Iterator> U> constexpr basic_const_iterator(basic_const_iterator<U> current);template<different-from<basic_const_iterator> T> requires convertible_to<T, Iterator> constexpr basic_const_iterator(T&& current);constexpr const Iterator& base() const & noexcept;constexpr Iterator base() &&;constexpr reference operator*() const;constexpr const auto* operator->() const requires is_lvalue_reference_v<iter_reference_t<Iterator>> && same_as<remove_cvref_t<iter_reference_t<Iterator>>, value_type>;constexpr basic_const_iterator& operator++();constexpr void operator++(int);constexpr basic_const_iterator operator++(int) requires forward_iterator<Iterator>;constexpr basic_const_iterator& operator--() requires bidirectional_iterator<Iterator>;constexpr basic_const_iterator operator--(int) requires bidirectional_iterator<Iterator>;constexpr basic_const_iterator& operator+=(difference_type n) requires random_access_iterator<Iterator>;constexpr basic_const_iterator& operator-=(difference_type n) requires random_access_iterator<Iterator>;constexpr reference operator[](difference_type n) const requires random_access_iterator<Iterator>;template<sentinel_for<Iterator> S> constexpr bool operator==(const S& s) const;template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator const&, CI> constexpr operator CI() const &;template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator, CI> constexpr operator CI() &&;constexpr bool operator<(const basic_const_iterator& y) const requires random_access_iterator<Iterator>;constexpr bool operator>(const basic_const_iterator& y) const requires random_access_iterator<Iterator>;constexpr bool operator<=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>;constexpr bool operator>=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>;constexpr auto operator<=>(const basic_const_iterator& y) const requires random_access_iterator<Iterator> && three_way_comparable<Iterator>;template<different-from<basic_const_iterator> I> constexpr bool operator<(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<different-from<basic_const_iterator> I> constexpr bool operator>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<different-from<basic_const_iterator> I> constexpr bool operator<=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<different-from<basic_const_iterator> I> constexpr bool operator>=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<different-from<basic_const_iterator> I> constexpr auto operator<=>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I> && three_way_comparable_with<Iterator, I>;template<not-a-const-iterator I> friend constexpr bool operator<(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<not-a-const-iterator I> friend constexpr bool operator>(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<not-a-const-iterator I> friend constexpr bool operator<=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;template<not-a-const-iterator I> friend constexpr bool operator>=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;friend constexpr basic_const_iterator operator+(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>;friend constexpr basic_const_iterator operator+(difference_type n,const basic_const_iterator& i) requires random_access_iterator<Iterator>;friend constexpr basic_const_iterator operator-(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>;template<sized_sentinel_for<Iterator> S> constexpr difference_type operator-(const S& y) const;template<not-a-const-iterator S> requires sized_sentinel_for<S, Iterator> friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y);friend constexpr rvalue-reference iter_move(const basic_const_iterator& i) noexcept(noexcept(static_cast<_rvalue-reference_>(ranges::iter_move(i.current_)))) { return static_cast<_rvalue-reference_>(ranges::iter_move(i.current_));} };}

Given some type I, the concept not-a-const-iterator is defined as falseif I is a specialization of basic_const_iterator andtrue otherwise.

24.5.3.4 Member types [const.iterators.types]

basic_const_iterator<Iterator>​::​iterator_concept is defined as follows:

In that case,basic_const_iterator<Iterator>​::​iterator_category denotes the type iterator_traits<​Iterator>​::​iterator_category.

24.5.3.5 Operations [const.iterators.ops]

constexpr basic_const_iterator(Iterator current);

Effects: Initializes current_ with std​::​move(current).

template<[convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<Iterator> U> constexpr basic_const_iterator(basic_const_iterator<U> current);

Effects: Initializes _current__with std​::​move(current.current_).

Effects: Initializes current_ with std​::​forward<T>(current).

constexpr const Iterator& base() const & noexcept;

Effects: Equivalent to: return current_;

constexpr Iterator base() &&;

Effects: Equivalent to: return std​::​move(current_);

constexpr _reference_ operator*() const;

Effects: Equivalent to: return static_cast<_reference_>(*current_);

constexpr const auto* operator->() const requires is_lvalue_reference_v<iter_reference_t<Iterator>> && [same_as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<iter_reference_t<Iterator>>, value_type>;

Returns: If Iterator models contiguous_iterator,to_address(current_); otherwise, addressof(*current_).

constexpr basic_const_iterator& operator++();

Effects: Equivalent to:++current_;return *this;

constexpr void operator++(int);

Effects: Equivalent to: ++current_;

constexpr basic_const_iterator operator++(int) requires [forward_iterator](iterator.concept.forward#concept:forward%5Fiterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<Iterator>;

Effects: Equivalent to:auto tmp = *this;++*this;return tmp;

Effects: Equivalent to:--current_;return *this;

Effects: Equivalent to:auto tmp = *this;--*this;return tmp;

Effects: Equivalent to:current_ op n;return *this;

Effects: Equivalent to: return static_cast<_reference_>(_current__[n]);

template<[sentinel_for](iterator.concept.sentinel#concept:sentinel%5Ffor "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<Iterator> S> constexpr bool operator==(const S& s) const;

Effects: Equivalent to: return current_ == s;

template<[_not-a-const-iterator_](#concept:not-a-const-iterator "24.5.3.3 Class template basic_­const_­iterator [const.iterators.iterator]") CI> requires [_constant-iterator_](#concept:constant-iterator "24.5.3.2 Alias templates [const.iterators.alias]")<CI> && [convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<Iterator const&, CI> constexpr operator CI() const &;

Returns: std​::​move(current_).

Effects: Equivalent to:return current_ op y.current_;

Effects: Equivalent to: return current_ op y;

Effects: Equivalent to: return x op y.current_;

friend constexpr basic_const_iterator operator+(const basic_const_iterator& i, difference_type n) requires [random_access_iterator](iterator.concept.random.access#concept:random%5Faccess%5Fiterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<Iterator>;friend constexpr basic_const_iterator operator+(difference_type n, const basic_const_iterator& i) requires [random_access_iterator](iterator.concept.random.access#concept:random%5Faccess%5Fiterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<Iterator>;

Effects: Equivalent to: return basic_const_iterator(i.current_ + n);

friend constexpr basic_const_iterator operator-(const basic_const_iterator& i, difference_type n) requires [random_access_iterator](iterator.concept.random.access#concept:random%5Faccess%5Fiterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<Iterator>;

Effects: Equivalent to: return basic_const_iterator(i.current_ - n);

template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized%5Fsentinel%5Ffor "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<Iterator> S> constexpr difference_type operator-(const S& y) const;

Effects: Equivalent to: return current_ - y;

template<[_not-a-const-iterator_](#concept:not-a-const-iterator "24.5.3.3 Class template basic_­const_­iterator [const.iterators.iterator]") S> requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized%5Fsentinel%5Ffor "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<S, Iterator> friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y);

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

24.5.4 Move iterators and sentinels [move.iterators]

24.5.4.1 General [move.iterators.general]

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 1: list<string> s; vector<string> v1(s.begin(), s.end()); vector<string> v2(make_move_iterator(s.begin()), make_move_iterator(s.end())); — _end example_]

24.5.4.2 Class template move_iterator [move.iterator]

namespace std { template<class Iterator> class move_iterator { public: using iterator_type = Iterator;using iterator_concept = see below;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 const Iterator& base() const & noexcept;constexpr Iterator 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; };}

The member typedef-name iterator_concept is defined as follows:

The member typedef-name iterator_category is defined if and only if the qualified-id iterator_traits<Iterator>​::​iterator_categoryis valid and denotes a type.

In that case, iterator_category denotes

24.5.4.3 Requirements [move.iter.requirements]

24.5.4.4 Construction and assignment [move.iter.cons]

constexpr move_iterator();

Effects: Value-initializes current.

constexpr explicit move_iterator(Iterator i);

Effects: Initializes current with std​::​move(i).

template<class U> constexpr move_iterator(const move_iterator<U>& u);

Constraints: is_same_v<U, Iterator> is false andconst U& models convertible_to<Iterator>.

Effects: Initializes current with u.current.

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

Effects: Assigns u.current tocurrent.

24.5.4.5 Conversion [move.iter.op.conv]

constexpr const Iterator& base() const & noexcept;

constexpr Iterator base() &&;

Returns: std​::​move(current).

24.5.4.6 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: return ranges​::​iter_move(current + n);

24.5.4.7 Navigation [move.iter.nav]

constexpr move_iterator& operator++();

Effects: As if by ++current.

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.

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;

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;

24.5.4.8 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.concept.sentinel#concept:sentinel%5Ffor "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<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.

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.

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.

template<class Iterator1, [three_way_comparable_with](cmp.concept#concept:three%5Fway%5Fcomparable%5Fwith "17.12.4 Concept three_­way_­comparable [cmp.concept]")<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().

24.5.4.9 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.concept.sizedsentinel#concept:sized%5Fsentinel%5Ffor "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y);template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized%5Fsentinel%5Ffor "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")<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.base() + n is well-formed and has type Iterator.

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](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<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)).

24.5.4.10 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 typeI and sentinel type S model sentinel_for<S, I>,move_sentinel<S> and move_iterator<I> modelsentinel_for<move_sentinel<S>, move_iterator<I>> as well.

[Example 1:

A move_if algorithm is easily implemented withcopy_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) { ranges::copy_if(move_iterator<I>{std::move(first)}, move_sentinel<S>{last}, std::move(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; };}

24.5.4.11 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](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s);

Effects: Initializes last with s.last.

template<class S2> requires [assignable_from](concept.assignable#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s);

Effects: Equivalent to: last = s.last; return *this;

constexpr S base() const;

24.5.5 Common iterators [iterators.common]

24.5.5.1 Class template common_iterator [common.iterator]

Class template common_iterator is an iterator/sentinel adaptor that is capable of representing a non-common range of elements (where the types of the iterator and sentinel differ) as a common 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 1:

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 1: template<class ForwardIterator> void fun(ForwardIterator begin, ForwardIterator end); list<int> s;using CI = common_iterator<counted_iterator<list<int>::iterator>, default_sentinel_t>; fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — _end example_]

namespace std { template<input_or_output_iterator I, sentinel_for<I> S> requires (same\_as<I, S> && copyable<I>) class common_iterator { public: constexpr common_iterator() requires default_initializable<I> = default;constexpr common_iterator(I i);constexpr common_iterator(S s);template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> && assignable_from<I&, const I2&> && assignable_from<S&, const S2&> constexpr common_iterator& operator=(const common_iterator<I2, S2>& x);constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires dereferenceable<const I>;constexpr auto operator->() const requires see below;constexpr common_iterator& operator++();constexpr decltype(auto) operator++(int);template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> && equality_comparable_with<I, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);template<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2> requires sized_sentinel_for<S, I2> friend constexpr iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires input_iterator<I>;template<indirectly_swappable<I> I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));private: variant<I, S> v_; };template<class I, class S> struct incrementable_traits<common_iterator<I, S>> { using difference_type = iter_difference_t<I>;};template<input_iterator I, class S> struct iterator_traits<common_iterator<I, S>> { using iterator_concept = see below;using iterator_category = see below; using value_type = iter_value_t<I>;using difference_type = iter_difference_t<I>;using pointer = see below;using reference = iter_reference_t<I>;};}

24.5.5.2 Associated types [common.iter.types]

The nested typedef-name iterator_category of the specialization of iterator_traits for common_iterator<I, S>is defined if and only if iter_difference_t<I> is an integral type.

In that case,iterator_category denotes forward_iterator_tag if the qualified-id iterator_traits<I>​::​iterator_categoryis valid and denotes a type that models derived_from<forward_iterator_tag>; otherwise it denotes input_iterator_tag.

The remaining nested typedef-names of the specialization ofiterator_traits for common_iterator<I, S> are defined as follows:

24.5.5.3 Constructors and conversions [common.iter.const]

constexpr common_iterator(I i);

Effects: Initializes v_ as if by v_{in_place_type<I>, std​::​move(i)}.

constexpr common_iterator(S s);

Effects: Initializes v_ as if byv_{in_place_type<S>, std​::​move(s)}.

template<class I2, class S2> requires [convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const I2&, I> && [convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);

Hardened preconditions: x.v_.valueless_by_exception() is false.

Effects: Initializes v_ as if byv_{in_place_index<i>, get<i>(x.v_)}, where i is x.v_.index().

Hardened preconditions: x.v_.valueless_by_exception() is false.

Effects: Equivalent to:

where i is x.v_.index().

24.5.5.4 Accessors [common.iter.access]

constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires [_dereferenceable_](iterator.synopsis#concept:dereferenceable "24.2 Header <iterator> synopsis [iterator.synopsis]")<const I>;

Hardened preconditions: holds_alternative<I>(v_) is true.

Effects: Equivalent to: return *get<I>(v_);

constexpr auto operator->() const requires _see below_;

Hardened preconditions: holds_alternative<I>(v_) is true.

Effects:

24.5.5.5 Navigation [common.iter.nav]

constexpr common_iterator& operator++();

Hardened preconditions: holds_alternative<I>(v_) is true.

Effects: Equivalent to ++get<I>(v_).

constexpr decltype(auto) operator++(int);

Hardened preconditions: holds_alternative<I>(v_) is true.

Effects: If I models forward_iterator, equivalent to:common_iterator tmp = *this;++*this;return tmp;

Otherwise, equivalent to:postfix-proxy p(**this);++*this;return p;where postfix-proxy is the exposition-only class:class postfix-proxy { iter_value_t<I> keep_;constexpr postfix-proxy(iter_reference_t<I>&& x) : keep_(std::forward<iter_reference_t<I>>(x)) {} public: constexpr const iter_value_t<I>& operator*() const noexcept { return keep_;} };

24.5.5.6 Comparisons [common.iter.cmp]

template<class I2, [sentinel_for](iterator.concept.sentinel#concept:sentinel%5Ffor "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<I> S2> requires [sentinel_for](iterator.concept.sentinel#concept:sentinel%5Ffor "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);

Hardened preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception()are each false.

Returns: true if i == j, and otherwise get<i>(x.v_) == get<j>(y.v_), where i is x.v_.index() and j is y.v_.index().

Hardened preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception()are each false.

Returns: true if i and j are each 1, and otherwiseget<i>(x.v_) == get<j>(y.v_), wherei is x.v_.index() and j is y.v_.index().

Hardened preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception()are each false.

Returns: 0 if i and j are each 1, and otherwiseget<i>(x.v_) - get<j>(y.v_), wherei is x.v_.index() and j is y.v_.index().

24.5.5.7 Customizations [common.iter.cust]

friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires [input_iterator](iterator.concept.input#concept:input%5Fiterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]")<I>;

Hardened preconditions: holds_alternative<I>(i.v_) is true.

Effects: Equivalent to: return ranges​::​iter_move(get<I>(i.v_));

template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<I> I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));

Hardened preconditions: holds_alternative<I>(x.v_) and holds_alternative<I2>(y.v_)are each true.

Effects: Equivalent to ranges​::​iter_swap(get<I>(x.v_), get<I2>(y.v_)).

24.5.6 Default sentinel [default.sentinel]

namespace std { struct default_sentinel_t { };}

Class default_sentinel_t is an empty type used to denote the end of a range.

It can be used together with iterator types that know the bound of their range (e.g., counted_iterator ([counted.iterator])).

24.5.7 Counted iterators [iterators.counted]

24.5.7.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_sentinelin 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; vector<string> v; ranges::copy(counted_iterator(s.begin(), 10), default_sentinel, back_inserter(v)); — _end example_]

Two values i1 and i2 of typescounted_iterator<I1>andcounted_iterator<I2>refer to elements of the same sequence if and only if there exists some integer n such thatnext(i1.base(), i1.count() + n)andnext(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>; using difference_type = iter_difference_t<I>;using iterator_concept = I::iterator_concept; using iterator_category = I::iterator_category; 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) noexcept;friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y) noexcept;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) noexcept;template<common_with<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y);friend constexpr decltype(auto) 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(); iter_difference_t<I> length = 0; };template<input_iterator I> requires same_as<_ITER_TRAITS_(I), iterator_traits<I>> struct iterator_traits<counted_iterator<I>> : iterator_traits<I> { using pointer = conditional_t<contiguous_iterator<I>, add_pointer_t<iter_reference_t<I>>, void>;};}

24.5.7.2 Constructors and conversions [counted.iter.const]

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

Hardened preconditions: n >= 0 is true.

Effects: Initializes current with std​::​move(i) andlength with n.

template<class I2> requires [convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_­to [concept.convertible]")<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x);

Effects: Initializes current with x.current andlength with x.length.

template<class I2> requires [assignable_from](concept.assignable#concept:assignable%5Ffrom "18.4.8 Concept assignable_­from [concept.assignable]")<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x);

Effects: Assigns x.current to current andx.length to length.

24.5.7.3 Accessors [counted.iter.access]

constexpr const I& base() const & noexcept;

Effects: Equivalent to: return current;

Returns: std​::​move(current).

constexpr iter_difference_t<I> count() const noexcept;

Effects: Equivalent to: return length;

24.5.7.4 Element access [counted.iter.elem]

constexpr decltype(auto) operator*();constexpr decltype(auto) operator*() const requires [_dereferenceable_](iterator.synopsis#concept:dereferenceable "24.2 Header <iterator> synopsis [iterator.synopsis]")<const I>;

Hardened preconditions: length > 0 is true.

Effects: Equivalent to: return *current;

Effects: Equivalent to: return to_address(current);

Hardened preconditions: n < length is true.

Effects: Equivalent to: return current[n];

24.5.7.5 Navigation [counted.iter.nav]

constexpr counted_iterator& operator++();

Hardened preconditions: length > 0 is true.

Effects: Equivalent to:++current;--length;return *this;

constexpr decltype(auto) operator++(int);

Hardened preconditions: length > 0 is true.

Effects: Equivalent to:--length;try { return current++; } catch(...) { ++length; throw; }

Effects: Equivalent to:counted_iterator tmp = *this;++*this;return tmp;

Effects: Equivalent to:--current;++length;return *this;

Effects: Equivalent to:counted_iterator tmp = *this;--*this;return tmp;

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 [random_access_iterator](iterator.concept.random.access#concept:random%5Faccess%5Fiterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<I>;

Effects: Equivalent to: return x + n;

Hardened preconditions: n <= length is true.

Effects: Equivalent to:current += n; length -= n;return *this;

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

template<[common_with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: 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) noexcept;

Effects: Equivalent to:return -x.length;

friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y) noexcept;

Effects: Equivalent to: return y.length;

Hardened preconditions: -n <= length is true.

Effects: Equivalent to:current -= n; length += n;return *this;

24.5.7.6 Comparisons [counted.iter.cmp]

template<[common_with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: 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) noexcept;

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

template<[common_with](concept.common#concept:common%5Fwith "18.4.6 Concept common_­with [concept.common]")<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y);

Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).

Effects: Equivalent to: return y.length <=> x.length;

[Note 1:

The argument order in the Effects: element is reversed because length counts down, not up.

— _end note_]

24.5.7.7 Customizations [counted.iter.cust]

friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires [input_iterator](iterator.concept.input#concept:input%5Fiterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]")<I>;

Hardened preconditions: i.length > 0 is true.

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

template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<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)));

Hardened preconditions: Both x.length > 0 and y.length > 0 are true.

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

24.5.8 Unreachable sentinel [unreachable.sentinel]

Class unreachable_sentinel_t can be used with any weakly_incrementable type to denote the “upper bound” of an unbounded interval.

[Example 1: char* p;char* nl = find(p, unreachable_sentinel, '\n');

Provided a newline character really exists in the buffer, the use ofunreachable_sentinel 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 { struct unreachable_sentinel_t { template<weakly_incrementable I> friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept { return false; } };}