Subclause | Header(s) | |
Iterator requirements | <iterator> | |
Iterator primitives | ||
Iterator adaptors | ||
Stream iterators | ||
Range access | ||
#include <concepts> namespace std { template<class T> using with-reference = T&; // exposition only template<class T> concept can-reference // exposition only = requires { typename with-reference<T>; }; template<class T> concept dereferenceable // exposition only = requires(T& t) { { *t } -> can-reference; // not required to be equality-preserving }; // [iterator.assoc.types], associated types // [incrementable.traits], incrementable traits template<class> struct incrementable_traits; template<class T> using iter_difference_t = see below; // [readable.traits], readable traits template<class> struct readable_traits; template<class T> using iter_value_t = see below; // [iterator.traits], iterator traits template<class I> struct iterator_traits; template<class T> struct iterator_traits<T*>; template<dereferenceable T> using iter_reference_t = decltype(*declval<T&>()); namespace ranges { // [iterator.cust], customization points inline namespace unspecified { // [iterator.cust.move], ranges::iter_move inline constexpr unspecified iter_move = unspecified; // [iterator.cust.swap], ranges::iter_swap inline constexpr unspecified iter_swap = unspecified; } } template<dereferenceable T> requires requires(T& t) { { ranges::iter_move(t) } -> can-reference; } using iter_rvalue_reference_t = decltype(ranges::iter_move(declval<T&>())); // [iterator.concepts], iterator concepts // [iterator.concept.readable], concept Readable template<class In> concept Readable = see below; template<Readable T> using iter_common_reference_t = common_reference_t<iter_reference_t<T>, iter_value_t<T>&>; // [iterator.concept.writable], concept Writable template<class Out, class T> concept Writable = see below; // [iterator.concept.winc], concept WeaklyIncrementable template<class I> concept WeaklyIncrementable = see below; // [iterator.concept.inc], concept Incrementable template<class I> concept Incrementable = see below; // [iterator.concept.iterator], concept Iterator template<class I> concept Iterator = see below; // [iterator.concept.sentinel], concept Sentinel template<class S, class I> concept Sentinel = see below; // [iterator.concept.sizedsentinel], concept SizedSentinel template<class S, class I> inline constexpr bool disable_sized_sentinel = false; template<class S, class I> concept SizedSentinel = see below; // [iterator.concept.input], concept InputIterator template<class I> concept InputIterator = see below; // [iterator.concept.output], concept OutputIterator template<class I, class T> concept OutputIterator = see below; // [iterator.concept.forward], concept ForwardIterator template<class I> concept ForwardIterator = see below; // [iterator.concept.bidir], concept BidirectionalIterator template<class I> concept BidirectionalIterator = see below; // [iterator.concept.random.access], concept RandomAccessIterator template<class I> concept RandomAccessIterator = see below; // [iterator.concept.contiguous], concept ContiguousIterator template<class I> concept ContiguousIterator = see below; // [indirectcallable], indirect callable requirements // [indirectcallable.indirectinvocable], indirect callables template<class F, class I> concept IndirectUnaryInvocable = see below; template<class F, class I> concept IndirectRegularUnaryInvocable = see below; template<class F, class I> concept IndirectUnaryPredicate = see below; template<class F, class I1, class I2 = I1> concept IndirectRelation = see below; template<class F, class I1, class I2 = I1> concept IndirectStrictWeakOrder = see below; template<class F, class... Is> requires (Readable<Is> && ...) && Invocable<F, iter_reference_t<Is>...> using indirect_result_t = invoke_result_t<F, iter_reference_t<Is>...>; // [projected], projected template<Readable I, IndirectRegularUnaryInvocable<I> Proj> struct projected; template<WeaklyIncrementable I, class Proj> struct incrementable_traits<projected<I, Proj>>; // [alg.req], common algorithm requirements // [alg.req.ind.move], concept IndirectlyMovable template<class In, class Out> concept IndirectlyMovable = see below; template<class In, class Out> concept IndirectlyMovableStorable = see below; // [alg.req.ind.copy], concept IndirectlyCopyable template<class In, class Out> concept IndirectlyCopyable = see below; template<class In, class Out> concept IndirectlyCopyableStorable = see below; // [alg.req.ind.swap], concept IndirectlySwappable template<class I1, class I2 = I1> concept IndirectlySwappable = see below; // [alg.req.ind.cmp], concept IndirectlyComparable template<class I1, class I2, class R, class P1 = identity, class P2 = identity> concept IndirectlyComparable = see below; // [alg.req.permutable], concept Permutable template<class I> concept Permutable = see below; // [alg.req.mergeable], concept Mergeable template<class I1, class I2, class Out, class R = ranges::less<>, class P1 = identity, class P2 = identity> concept Mergeable = see below; // [alg.req.sortable], concept Sortable template<class I, class R = ranges::less<>, class P = identity> concept Sortable = see below; // [iterator.primitives], primitives // [std.iterator.tags], iterator tags struct input_iterator_tag { }; struct output_iterator_tag { }; struct forward_iterator_tag: public input_iterator_tag { }; struct bidirectional_iterator_tag: public forward_iterator_tag { }; struct random_access_iterator_tag: public bidirectional_iterator_tag { }; struct contiguous_iterator_tag: public random_access_iterator_tag { }; // [iterator.operations], iterator operations template<class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n); template<class InputIterator> constexpr typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last); template<class InputIterator> constexpr InputIterator next(InputIterator x, typename iterator_traits<InputIterator>::difference_type n = 1); template<class BidirectionalIterator> constexpr BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits<BidirectionalIterator>::difference_type n = 1); // [range.iter.ops], range iterator operations namespace ranges { // [range.iter.op.advance], ranges::advance template<Iterator I> constexpr void advance(I& i, iter_difference_t<I> n); template<Iterator I, Sentinel<I> S> constexpr void advance(I& i, S bound); template<Iterator I, Sentinel<I> S> constexpr iter_difference_t<I> advance(I& i, iter_difference_t<I> n, S bound); // [range.iter.op.distance], ranges::distance template<Iterator I, Sentinel<I> S> constexpr iter_difference_t<I> distance(I first, S last); template<Range R> constexpr iter_difference_t<iterator_t<R>> distance(R&& r); // [range.iter.op.next], ranges::next template<Iterator I> constexpr I next(I x); template<Iterator I> constexpr I next(I x, iter_difference_t<I> n); template<Iterator I, Sentinel<I> S> constexpr I next(I x, S bound); template<Iterator I, Sentinel<I> S> constexpr I next(I x, iter_difference_t<I> n, S bound); // [range.iter.op.prev], ranges::prev template<BidirectionalIterator I> constexpr I prev(I x); template<BidirectionalIterator I> constexpr I prev(I x, iter_difference_t<I> n); template<BidirectionalIterator I> constexpr I prev(I x, iter_difference_t<I> n, I bound); } // [predef.iterators], predefined iterators and sentinels // [reverse.iterators], reverse iterators template<class Iterator> class reverse_iterator; template<class Iterator1, class Iterator2> constexpr bool operator==( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator!=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr auto operator-( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base()); template<class Iterator> constexpr reverse_iterator<Iterator> operator+( typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& x); template<class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i); template<class Iterator1, class Iterator2> requires (!SizedSentinel<Iterator1, Iterator2>) inline constexpr bool disable_sized_sentinel<reverse_iterator<Iterator1>, reverse_iterator<Iterator2>> = true; // [insert.iterators], insert iterators template<class Container> class back_insert_iterator; template<class Container> constexpr back_insert_iterator<Container> back_inserter(Container& x); template<class Container> class front_insert_iterator; template<class Container> constexpr front_insert_iterator<Container> front_inserter(Container& x); template<class Container> class insert_iterator; template<class Container> constexpr insert_iterator<Container> inserter(Container& x, iterator_t<Container> i); // [move.iterators], move iterators and sentinels template<class Iterator> class move_iterator; template<class Iterator1, class Iterator2> constexpr bool operator==( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator!=( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<=( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>=( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr auto operator-( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); template<class Iterator> constexpr move_iterator<Iterator> operator+( typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& x); template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i); template<Semiregular S> class move_sentinel; // [iterators.common], common iterators template<Iterator I, Sentinel<I> S> requires (!Same<I, S>) class common_iterator; template<class I, class S> struct incrementable_traits<common_iterator<I, S>>; template<InputIterator I, class S> struct iterator_traits<common_iterator<I, S>>; // [default.sentinels], default sentinels struct default_sentinel_t; inline constexpr default_sentinel_t default_sentinel{}; // [iterators.counted], counted iterators template<Iterator I> class counted_iterator; template<class I> struct incrementable_traits<counted_iterator<I>>; template<InputIterator I> struct iterator_traits<counted_iterator<I>>; // [unreachable.sentinels], unreachable sentinels struct unreachable_sentinel_t; inline constexpr unreachable_sentinel_t unreachable_sentinel{}; // [stream.iterators], stream iterators template<class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> class istream_iterator; template<class T, class charT, class traits, class Distance> bool operator==(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y); template<class T, class charT, class traits, class Distance> bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y); template<class T, class charT = char, class traits = char_traits<charT>> class ostream_iterator; template<class charT, class traits = char_traits<charT>> class istreambuf_iterator; template<class charT, class traits> bool operator==(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b); template<class charT, class traits> bool operator!=(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b); template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator; // [iterator.range], range access template<class C> constexpr auto begin(C& c) -> decltype(c.begin()); template<class C> constexpr auto begin(const C& c) -> decltype(c.begin()); template<class C> constexpr auto end(C& c) -> decltype(c.end()); template<class C> constexpr auto end(const C& c) -> decltype(c.end()); template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept; template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept; template<class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c)); template<class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c)); template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin()); template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin()); template<class C> constexpr auto rend(C& c) -> decltype(c.rend()); template<class C> constexpr auto rend(const C& c) -> decltype(c.rend()); template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]); template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]); template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il); template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il); template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c)); template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c)); template<class C> constexpr auto size(const C& c) -> decltype(c.size()); template<class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept; template<class C> [[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty()); template<class T, size_t N> [[nodiscard]] constexpr bool empty(const T (&array)[N]) noexcept; template<class E> [[nodiscard]] constexpr bool empty(initializer_list<E> il) noexcept; template<class C> constexpr auto data(C& c) -> decltype(c.data()); template<class C> constexpr auto data(const C& c) -> decltype(c.data()); template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept; template<class E> constexpr const E* data(initializer_list<E> il) noexcept; }
Contiguous | → Random Access | → Bidirectional | → Forward | → Input |
→ Output |
iter_difference_t<WI>be defined as the incrementable type's difference type.
namespace std { template<class> struct incrementable_traits { }; template<class T> requires is_object_v<T> struct incrementable_traits<T*> { using difference_type = ptrdiff_t; }; template<class I> struct incrementable_traits<const I> : incrementable_traits<I> { }; template<class T> requires requires { typename T::difference_type; } struct incrementable_traits<T> { using difference_type = typename T::difference_type; }; template<class T> requires (!requires { typename T::difference_type; } && requires(const T& a, const T& b) { { a - b } -> Integral; }) struct incrementable_traits<T> { using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>; }; template<class T> using iter_difference_t = see below; }
iter_value_t<R>be defined as the readable type's value type.
template<class> struct cond-value-type { }; // exposition only template<class T> requires is_object_v<T> struct cond-value-type { using value_type = remove_cv_t<T>; }; template<class> struct readable_traits { }; template<class T> struct readable_traits<T*> : cond-value-type<T> { }; template<class I> requires is_array_v<I> struct readable_traits<I> { using value_type = remove_cv_t<remove_extent_t<I>>; }; template<class I> struct readable_traits<const I> : readable_traits<I> { }; template<class T> requires requires { typename T::value_type; } struct readable_traits<T> : cond-value-type<typename T::value_type> { }; template<class T> requires requires { typename T::element_type; } struct readable_traits<T> : cond-value-type<typename T::element_type> { }; template<class T> using iter_value_t = see below;
iterator_traits<I>::iterator_categorybe defined as the iterator's iterator category.
iterator_traits<I>::pointer iterator_traits<I>::referenceshall be defined as the iterator's pointer and reference types; that is, for an iterator object a of class type, the same type as decltype(a.operator->()) and decltype(*a), respectively.
iterator_traits<I>::value_type iterator_traits<I>::difference_type iterator_traits<I>::referencemay be defined as void.
template<class I> concept cpp17-iterator = Copyable<I> && requires(I i) { { *i } -> can-reference; { ++i } -> Same<I&>; { *i++ } -> can-reference; }; template<class I> concept cpp17-input-iterator = cpp17-iterator<I> && EqualityComparable<I> && requires(I i) { typename incrementable_traits<I>::difference_type; typename readable_traits<I>::value_type; typename common_reference_t<iter_reference_t<I>&&, typename readable_traits<I>::value_type&>; *i++; typename common_reference_t<decltype(*i++)&&, typename readable_traits<I>::value_type&>; requires SignedIntegral<typename incrementable_traits<I>::difference_type>; }; template<class I> concept cpp17-forward-iterator = cpp17-input-iterator<I> && Constructible<I> && is_lvalue_reference_v<iter_reference_t<I>> && Same<remove_cvref_t<iter_reference_t<I>>, typename readable_traits<I>::value_type> && requires(I i) { { i++ } -> const I&; { *i++ } -> Same<iter_reference_t<I>>; }; template<class I> concept cpp17-bidirectional-iterator = cpp17-forward-iterator<I> && requires(I i) { { --i } -> Same<I&>; { i-- } -> const I&; { *i-- } -> Same<iter_reference_t<I>>; }; template<class I> concept cpp17-random-access-iterator = cpp17-bidirectional-iterator<I> && StrictTotallyOrdered<I> && requires(I i, typename incrementable_traits<I>::difference_type n) { { i += n } -> Same<I&>; { i -= n } -> Same<I&>; { i + n } -> Same<I>; { n + i } -> Same<I>; { i - n } -> Same<I>; { i - i } -> Same<decltype(n)>; { i[n] } -> iter_reference_t<I>; };
using iterator_category = typename I::iterator_category; using value_type = typename I::value_type; using difference_type = typename I::difference_type; using pointer = see below; using reference = typename I::reference;
using iterator_category = see below; using value_type = typename readable_traits<I>::value_type; using difference_type = typename incrementable_traits<I>::difference_type; using pointer = see below; using reference = see below;
using iterator_category = output_iterator_tag; using value_type = void; using difference_type = see below; using pointer = void; using reference = void;
namespace std { template<class T> requires is_object_v<T> struct iterator_traits<T*> { using iterator_concept = contiguous_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = remove_cv_t<T>; using difference_type = ptrdiff_t; using pointer = T*; using reference = T&; }; }
template<class BI> void reverse(BI first, BI last) { typename iterator_traits<BI>::difference_type n = distance(first, last); --n; while(n > 0) { typename iterator_traits<BI>::value_type tmp = *first; *first++ = *--last; *last = tmp; n -= 2; } }— end example
template<class X, class Y>
constexpr iter_value_t<remove_reference_t<X>> iter-exchange-move(X&& x, Y&& y)
noexcept(noexcept(iter_value_t<remove_reference_t<X>>(iter_move(x))) &&
noexcept(*x = iter_move(y)));
iter_value_t<remove_reference_t<X>> old_value(iter_move(x)); *x = iter_move(y); return old_value;
template<class I1, class I2> void iter_swap(I1, I2) = delete;and does not include a declaration of ranges::iter_swap.
struct I { using value_type = int; using difference_type = int; int operator*() const; I& operator++(); I operator++(int); I& operator--(); I operator--(int); bool operator==(I) const; bool operator!=(I) const; };iterator_traits<I>::iterator_category denotes input_iterator_tag, and ITER_CONCEPT(I) denotes random_access_iterator_tag.
template<class In> concept Readable = requires { typename iter_value_t<In>; typename iter_reference_t<In>; typename iter_rvalue_reference_t<In>; } && CommonReference<iter_reference_t<In>&&, iter_value_t<In>&> && CommonReference<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> && CommonReference<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;
template<class Out, class T> concept Writable = requires(Out&& o, T&& t) { *o = std::forward<T>(t); // not required to be equality-preserving *std::forward<Out>(o) = std::forward<T>(t); // not required to be equality-preserving const_cast<const iter_reference_t<Out>&&>(*o) = std::forward<T>(t); // not required to be equality-preserving const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) = std::forward<T>(t); // not required to be equality-preserving };
template<class I> concept WeaklyIncrementable = Semiregular<I> && requires(I i) { typename iter_difference_t<I>; requires SignedIntegral<iter_difference_t<I>>; { ++i } -> Same<I&>; // not required to be equality-preserving i++; // not required to be equality-preserving };
template<class I> concept Incrementable = Regular<I> && WeaklyIncrementable<I> && requires(I i) { { i++ } -> Same<I>; };
template<class I> concept Iterator = requires(I i) { { *i } -> can-reference; } && WeaklyIncrementable<I>;
template<class S, class I>
concept Sentinel =
Semiregular<S> &&
Iterator<I> &&
weakly-equality-comparable-with<S, I>; // See [concept.equalitycomparable]
template<class S, class I>
concept SizedSentinel =
Sentinel<S, I> &&
!disable_sized_sentinel<remove_cv_t<S>, remove_cv_t<I>> &&
requires(const I& i, const S& s) {
{ s - i } -> Same<iter_difference_t<I>>;
{ i - s } -> Same<iter_difference_t<I>>;
};
template<class I> concept InputIterator = Iterator<I> && Readable<I> && requires { typename ITER_CONCEPT(I); } && DerivedFrom<ITER_CONCEPT(I), input_iterator_tag>;
template<class I, class T> concept OutputIterator = Iterator<I> && Writable<I, T> && requires(I i, T&& t) { *i++ = std::forward<T>(t); // not required to be equality-preserving };
*i = E; ++i;
template<class I> concept ForwardIterator = InputIterator<I> && DerivedFrom<ITER_CONCEPT(I), forward_iterator_tag> && Incrementable<I> && Sentinel<I, I>;
template<class I> concept BidirectionalIterator = ForwardIterator<I> && DerivedFrom<ITER_CONCEPT(I), bidirectional_iterator_tag> && requires(I i) { { --i } -> Same<I&>; { i-- } -> Same<I>; };
template<class I> concept RandomAccessIterator = BidirectionalIterator<I> && DerivedFrom<ITER_CONCEPT(I), random_access_iterator_tag> && StrictTotallyOrdered<I> && SizedSentinel<I, I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> Same<I&>; { j + n } -> Same<I>; { n + j } -> Same<I>; { i -= n } -> Same<I&>; { j - n } -> Same<I>; { j[n] } -> Same<iter_reference_t<I>>; };
template<class I> concept ContiguousIterator = RandomAccessIterator<I> && DerivedFrom<ITER_CONCEPT(I), contiguous_iterator_tag> && is_lvalue_reference_v<iter_reference_t<I>> && Same<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>>;
Expression | Return type | Operational | Assertion/note |
semantics | pre-/post-condition | ||
a != b | contextually convertible to bool | !(a == b) | |
*a | reference, convertible to T | ||
a->m | (*a).m | ||
++r | X& | Ensures: r is dereferenceable or r is past-the-end; any copies of the previous value of r are no longer required to be dereferenceable nor to be in the domain of ==. | |
(void)r++ | equivalent to (void)++r | ||
*r++ | convertible to T | { T tmp = *r; ++r; return tmp; } |
Expression | Return type | Operational | Assertion/note |
semantics | pre-/post-condition | ||
r++ | convertible to const X& | { X tmp = r; ++r; return tmp; } | |
*r++ | reference |
Expression | Return type | Operational | Assertion/note |
semantics | pre-/post-condition | ||
--r | X& | ||
r-- | convertible to const X& | { X tmp = r; --r; return tmp; } | |
*r-- | reference |
Expression | Return type | Operational | Assertion/note |
semantics | pre-/post-condition | ||
r += n | X& | { difference_type m = n; if (m >= 0) while (m--) ++r; else while (m++) --r; return r; } | |
a + n n + a | X | { X tmp = a; return tmp += n; } | a + n == n + a. |
r -= n | X& | return r += -n; | |
a - n | X | { X tmp = a; return tmp -= n; } | |
b - a | difference_type | return n | |
a[n] | convertible to reference | *(a + n) | |
a < b | contextually
convertible to bool | b - a > 0 | < is a total ordering relation |
a > b | contextually
convertible to bool | b < a | |
a >= b | contextually
convertible to bool | !(a < b) | |
a <= b | contextually
convertible to bool. | !(a > b) |
namespace std { template<class F, class I> concept IndirectUnaryInvocable = Readable<I> && CopyConstructible<F> && Invocable<F&, iter_value_t<I>&> && Invocable<F&, iter_reference_t<I>> && Invocable<F&, iter_common_reference_t<I>> && CommonReference< invoke_result_t<F&, iter_value_t<I>&>, invoke_result_t<F&, iter_reference_t<I>>>; template<class F, class I> concept IndirectRegularUnaryInvocable = Readable<I> && CopyConstructible<F> && RegularInvocable<F&, iter_value_t<I>&> && RegularInvocable<F&, iter_reference_t<I>> && RegularInvocable<F&, iter_common_reference_t<I>> && CommonReference< invoke_result_t<F&, iter_value_t<I>&>, invoke_result_t<F&, iter_reference_t<I>>>; template<class F, class I> concept IndirectUnaryPredicate = Readable<I> && CopyConstructible<F> && Predicate<F&, iter_value_t<I>&> && Predicate<F&, iter_reference_t<I>> && Predicate<F&, iter_common_reference_t<I>>; template<class F, class I1, class I2 = I1> concept IndirectRelation = Readable<I1> && Readable<I2> && CopyConstructible<F> && Relation<F&, iter_value_t<I1>&, iter_value_t<I2>&> && Relation<F&, iter_value_t<I1>&, iter_reference_t<I2>> && Relation<F&, iter_reference_t<I1>, iter_value_t<I2>&> && Relation<F&, iter_reference_t<I1>, iter_reference_t<I2>> && Relation<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>; template<class F, class I1, class I2 = I1> concept IndirectStrictWeakOrder = Readable<I1> && Readable<I2> && CopyConstructible<F> && StrictWeakOrder<F&, iter_value_t<I1>&, iter_value_t<I2>&> && StrictWeakOrder<F&, iter_value_t<I1>&, iter_reference_t<I2>> && StrictWeakOrder<F&, iter_reference_t<I1>, iter_value_t<I2>&> && StrictWeakOrder<F&, iter_reference_t<I1>, iter_reference_t<I2>> && StrictWeakOrder<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>; }
namespace std { template<Readable I, IndirectRegularUnaryInvocable<I> Proj> struct projected { using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>; indirect_result_t<Proj&, I> operator*() const; // not defined }; template<WeaklyIncrementable I, class Proj> struct incrementable_traits<projected<I, Proj>> { using difference_type = iter_difference_t<I>; }; }
template<class In, class Out> concept IndirectlyMovable = Readable<In> && Writable<Out, iter_rvalue_reference_t<In>>;
template<class In, class Out> concept IndirectlyMovableStorable = IndirectlyMovable<In, Out> && Writable<Out, iter_value_t<In>> && Movable<iter_value_t<In>> && Constructible<iter_value_t<In>, iter_rvalue_reference_t<In>> && Assignable<iter_value_t<In>&, iter_rvalue_reference_t<In>>;
iter_value_t<In> obj(ranges::iter_move(i));obj is equal to the value previously denoted by *i.
template<class In, class Out> concept IndirectlyCopyable = Readable<In> && Writable<Out, iter_reference_t<In>>;
template<class In, class Out> concept IndirectlyCopyableStorable = IndirectlyCopyable<In, Out> && Writable<Out, const iter_value_t<In>&> && Copyable<iter_value_t<In>> && Constructible<iter_value_t<In>, iter_reference_t<In>> && Assignable<iter_value_t<In>&, iter_reference_t<In>>;
iter_value_t<In> obj(*i);obj is equal to the value previously denoted by *i.
template<class I1, class I2 = I1> concept IndirectlySwappable = Readable<I1> && Readable<I2> && requires(I1& i1, I2& i2) { ranges::iter_swap(i1, i1); ranges::iter_swap(i2, i2); ranges::iter_swap(i1, i2); ranges::iter_swap(i2, i1); };
template<class I1, class I2, class R, class P1 = identity, class P2 = identity> concept IndirectlyComparable = IndirectRelation<R, projected<I1, P1>, projected<I2, P2>>;
template<class I1, class I2, class Out, class R = ranges::less<>, class P1 = identity, class P2 = identity> concept Mergeable = InputIterator<I1> && InputIterator<I2> && WeaklyIncrementable<Out> && IndirectlyCopyable<I1, Out> && IndirectlyCopyable<I2, Out> && IndirectStrictWeakOrder<R, projected<I1, P1>, projected<I2, P2>>;
template<class InputIterator, class Distance>
constexpr void advance(InputIterator& i, Distance n);
template<class InputIterator>
constexpr typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
template<class InputIterator>
constexpr InputIterator next(InputIterator x,
typename iterator_traits<InputIterator>::difference_type n = 1);
template<class BidirectionalIterator>
constexpr BidirectionalIterator prev(BidirectionalIterator x,
typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
void foo() { using namespace std::ranges; std::vector<int> vec{1,2,3}; distance(begin(vec), end(vec)); // #1 }
template<Iterator I>
constexpr void ranges::advance(I& i, iter_difference_t<I> n);
template<Iterator I, Sentinel<I> S>
constexpr void ranges::advance(I& i, S bound);
template<Iterator I, Sentinel<I> S>
constexpr iter_difference_t<I> ranges::advance(I& i, iter_difference_t<I> n, S bound);
template<Iterator I, Sentinel<I> S>
constexpr iter_difference_t<I> ranges::distance(I first, S last);
template<Range R>
constexpr iter_difference_t<iterator_t<R>> ranges::distance(R&& r);
return ranges::distance(ranges::begin(r), ranges::end(r)); // [range.access]
template<Iterator I>
constexpr I ranges::next(I x);
template<Iterator I>
constexpr I ranges::next(I x, iter_difference_t<I> n);
template<Iterator I, Sentinel<I> S>
constexpr I ranges::next(I x, S bound);
template<Iterator I, Sentinel<I> S>
constexpr I ranges::next(I x, iter_difference_t<I> n, S bound);
template<BidirectionalIterator I>
constexpr I ranges::prev(I x);
template<BidirectionalIterator I>
constexpr I ranges::prev(I x, iter_difference_t<I> n);
template<BidirectionalIterator I>
constexpr I ranges::prev(I x, iter_difference_t<I> n, I bound);
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 = typename 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<IndirectlySwappable<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<Iterator2>& y) noexcept(see below); protected: Iterator current; }; }
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 reference operator*() const;
constexpr pointer operator->() const
requires (is_pointer_v<Iterator> ||
requires (const Iterator i) { i.operator->(); });
constexpr unspecified operator[](difference_type n) const;
template<class Iterator1, class Iterator2>
constexpr bool operator==(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator!=(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator<(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator>(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator<=(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator>=(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr auto operator-(
const reverse_iterator<Iterator1>& x,
const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());
template<class Iterator>
constexpr reverse_iterator<Iterator> operator+(
typename reverse_iterator<Iterator>::difference_type n,
const reverse_iterator<Iterator>& x);
friend constexpr iter_rvalue_reference_t<Iterator>
iter_move(const reverse_iterator& i) noexcept(see below);
is_nothrow_copy_constructible_v<Iterator> && noexcept(ranges::iter_move(--declval<Iterator&>()))
template<IndirectlySwappable<Iterator> Iterator2>
friend constexpr void
iter_swap(const reverse_iterator& x,
const reverse_iterator<Iterator2>& y) noexcept(see below);
auto xtmp = x.base(); auto ytmp = y.base(); ranges::iter_swap(--xtmp, --ytmp);
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);
while (first != last) *result++ = *first++;
namespace std { template<class Container> class back_insert_iterator { protected: Container* container = nullptr; 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 back_insert_iterator() noexcept = default; 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); }; }
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);
template<class Container>
constexpr back_insert_iterator<Container> back_inserter(Container& x);
namespace std { template<class Container> class front_insert_iterator { protected: Container* container = nullptr; 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 front_insert_iterator(Container& x) noexcept = default; 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); }; }
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);
template<class Container>
constexpr front_insert_iterator<Container> front_inserter(Container& x);
namespace std { template<class Container> class insert_iterator { protected: Container* container = nullptr; iterator_t<Container> iter = iterator_t<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; insert_iterator() = default; constexpr insert_iterator(Container& x, 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); }; }
constexpr insert_iterator(Container& x, 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);
template<class Container>
constexpr insert_iterator<Container>
inserter(Container& x, iterator_t<Container> i);
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 { template<class Iterator> class move_iterator { public: using iterator_type = Iterator; using iterator_concept = input_iterator_tag; 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 iterator_type base() const; constexpr reference operator*() const; constexpr pointer 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<Iterator> S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel<S>& y); template<Sentinel<Iterator> S> friend constexpr bool operator==(const move_sentinel<S>& x, const move_iterator& y); template<Sentinel<Iterator> S> friend constexpr bool operator!=(const move_iterator& x, const move_sentinel<S>& y); template<Sentinel<Iterator> S> friend constexpr bool operator!=(const move_sentinel<S>& x, const move_iterator& y); template<SizedSentinel<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y); template<SizedSentinel<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<IndirectlySwappable<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; // exposition only }; }
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 reference operator*() const;
constexpr pointer operator->() const;
constexpr reference operator[](difference_type n) const;
template<class Iterator1, class Iterator2>
constexpr bool operator==(const move_iterator<Iterator1>& x,
const move_iterator<Iterator2>& y);
template<Sentinel<Iterator> S>
friend constexpr bool operator==(const move_iterator& x,
const move_sentinel<S>& y);
template<Sentinel<Iterator> S>
friend constexpr bool operator==(const move_sentinel<S>& x,
const move_iterator& y);
template<class Iterator1, class Iterator2>
constexpr bool operator!=(const move_iterator<Iterator1>& x,
const move_iterator<Iterator2>& y);
template<Sentinel<Iterator> S>
friend constexpr bool operator!=(const move_iterator& x,
const move_sentinel<S>& y);
template<Sentinel<Iterator> S>
friend constexpr bool operator!=(const move_sentinel<S>& x,
const move_iterator& y);
template<class Iterator1, class Iterator2>
constexpr bool operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr bool operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
template<class Iterator1, class Iterator2>
constexpr auto operator-(const move_iterator<Iterator1>& x,
const move_iterator<Iterator2>& y)
-> decltype(x.base() - y.base());
template<SizedSentinel<Iterator> S>
friend constexpr iter_difference_t<Iterator>
operator-(const move_sentinel<S>& x, const move_iterator& y);
template<SizedSentinel<Iterator> S>
friend constexpr iter_difference_t<Iterator>
operator-(const move_iterator& x, const move_sentinel<S>& y);
template<class Iterator>
constexpr move_iterator<Iterator>
operator+(iter_difference_t<Iterator> n, const move_iterator<Iterator>& x);
friend constexpr iter_rvalue_reference_t<Iterator>
iter_move(const move_iterator& i)
noexcept(noexcept(ranges::iter_move(i.current)));
template<IndirectlySwappable<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)));
template<class Iterator>
constexpr move_iterator<Iterator> make_move_iterator(Iterator i);
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) { std::ranges::copy_if(move_iterator<I>{first}, move_sentinel<S>{last}, 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 ConvertibleTo<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s); template<class S2> requires Assignable<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s); constexpr S base() const; private: S last; // exposition only }; }
constexpr move_sentinel();
constexpr explicit move_sentinel(S s);
template<class S2>
requires ConvertibleTo<const S2&, S>
constexpr move_sentinel(const move_sentinel<S2>& s);
template<class S2>
requires Assignable<S&, const S2&>
constexpr move_sentinel& operator=(const move_sentinel<S2>& s);
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_t>; // call fun on a range of 10 ints fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel));— end example
namespace std { template<Iterator I, Sentinel<I> S> requires (!Same<I, S>) class common_iterator { public: constexpr common_iterator() = default; constexpr common_iterator(I i); constexpr common_iterator(S s); template<class I2, class S2> requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x); template<class I2, class S2> requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S> && Assignable<I&, const I2&> && Assignable<S&, const S2&> common_iterator& operator=(const common_iterator<I2, S2>& x); 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); template<class I2, Sentinel<I> S2> requires Sentinel<S, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y); template<class I2, Sentinel<I> S2> requires Sentinel<S, I2> && EqualityComparableWith<I, I2> friend bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y); template<class I2, Sentinel<I> S2> requires Sentinel<S, I2> friend bool operator!=( const common_iterator& x, const common_iterator<I2, S2>& y); template<SizedSentinel<I> I2, SizedSentinel<I> S2> requires SizedSentinel<S, I2> friend iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y); friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires InputIterator<I>; template<IndirectlySwappable<I> I2, class S2> friend 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_; // exposition only }; template<class I, class S> struct incrementable_traits<common_iterator<I, S>> { using difference_type = iter_difference_t<I>; }; template<InputIterator 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>; }; }
constexpr common_iterator(I i);
constexpr common_iterator(S s);
template<class I2, class S2>
requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S>
constexpr common_iterator(const common_iterator<I2, S2>& x);
template<class I2, class S2>
requires ConvertibleTo<const I2&, I> && ConvertibleTo<const S2&, S> &&
Assignable<I&, const I2&> && Assignable<S&, const S2&>
common_iterator& operator=(const common_iterator<I2, S2>& x);
decltype(auto) operator*();
decltype(auto) operator*() const
requires dereferenceable<const I>;
decltype(auto) operator->() const
requires see below;
Readable<const I> && (requires(const I& i) { i.operator->(); } || is_reference_v<iter_reference_t<I>> || Constructible<iter_value_t<I>, iter_reference_t<I>>)
auto&& tmp = *get<I>(v_); return addressof(tmp);
class proxy { iter_value_t<I> keep_; proxy(iter_reference_t<I>&& x) : keep_(std::move(x)) {} public: const iter_value_t<I>* operator->() const { return addressof(keep_); } };
template<class I2, Sentinel<I> S2>
requires Sentinel<S, I2>
friend bool operator==(
const common_iterator& x, const common_iterator<I2, S2>& y);
template<class I2, Sentinel<I> S2>
requires Sentinel<S, I2> && EqualityComparableWith<I, I2>
friend bool operator==(
const common_iterator& x, const common_iterator<I2, S2>& y);
template<class I2, Sentinel<I> S2>
requires Sentinel<S, I2>
friend bool operator!=(
const common_iterator& x, const common_iterator<I2, S2>& y);
template<SizedSentinel<I> I2, SizedSentinel<I> S2>
requires SizedSentinel<S, I2>
friend iter_difference_t<I2> operator-(
const common_iterator& x, const common_iterator<I2, S2>& y);
friend iter_rvalue_reference_t<I> iter_move(const common_iterator& i)
noexcept(noexcept(ranges::iter_move(declval<const I&>())))
requires InputIterator<I>;
template<IndirectlySwappable<I> I2, class S2>
friend void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));
namespace std {
struct default_sentinel_t { };
}
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
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; }; }
constexpr counted_iterator(I i, 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 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)));
char* p; // set p to point to a character buffer containing newlines char* nl = find(p, unreachable_sentinel, '\n');
namespace std { struct unreachable_sentinel_t { template<WeaklyIncrementable I> friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept; template<WeaklyIncrementable I> friend constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept; template<WeaklyIncrementable I> friend constexpr bool operator!=(unreachable_sentinel_t, const I&) noexcept; template<WeaklyIncrementable I> friend constexpr bool operator!=(const I&, unreachable_sentinel_t) noexcept; }; }
template<WeaklyIncrementable I>
friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept;
template<WeaklyIncrementable I>
friend constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept;
template<WeaklyIncrementable I>
friend constexpr bool operator!=(unreachable_sentinel_t, const I&) noexcept;
template<WeaklyIncrementable I>
friend constexpr bool operator!=(const I&, unreachable_sentinel_t) noexcept;
namespace std { template<class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> class istream_iterator { public: using iterator_category = input_iterator_tag; using value_type = T; using difference_type = Distance; using pointer = const T*; using reference = const T&; using char_type = charT; using traits_type = traits; using istream_type = basic_istream<charT,traits>; constexpr istream_iterator(); constexpr istream_iterator(default_sentinel_t); istream_iterator(istream_type& s); istream_iterator(const istream_iterator& x) = default; ~istream_iterator() = default; istream_iterator& operator=(const istream_iterator&) = default; const T& operator*() const; const T* operator->() const; istream_iterator& operator++(); istream_iterator operator++(int); friend bool operator==(const istream_iterator& i, default_sentinel_t); friend bool operator==(default_sentinel_t, const istream_iterator& i); friend bool operator!=(const istream_iterator& x, default_sentinel_t y); friend bool operator!=(default_sentinel_t x, const istream_iterator& y); private: basic_istream<charT,traits>* in_stream; // exposition only T value; // exposition only }; }
constexpr istream_iterator();
constexpr istream_iterator(default_sentinel_t);
istream_iterator(istream_type& s);
istream_iterator(const istream_iterator& x) = default;
~istream_iterator() = default;
const T& operator*() const;
const T* operator->() const;
istream_iterator& operator++();
istream_iterator operator++(int);
template<class T, class charT, class traits, class Distance>
bool operator==(const istream_iterator<T,charT,traits,Distance>& x,
const istream_iterator<T,charT,traits,Distance>& y);
friend bool operator==(default_sentinel_t, const istream_iterator& i);
friend bool operator==(const istream_iterator& i, default_sentinel_t);
template<class T, class charT, class traits, class Distance>
bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
const istream_iterator<T,charT,traits,Distance>& y);
friend bool operator!=(default_sentinel_t x, const istream_iterator& y);
friend bool operator!=(const istream_iterator& x, default_sentinel_t y);
namespace std { template<class T, class charT = char, class traits = char_traits<charT>> class ostream_iterator { public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using char_type = charT; using traits_type = traits; using ostream_type = basic_ostream<charT,traits>; constexpr ostreambuf_iterator() noexcept = default; ostream_iterator(ostream_type& s); ostream_iterator(ostream_type& s, const charT* delimiter); ostream_iterator(const ostream_iterator& x); ~ostream_iterator(); ostream_iterator& operator=(const ostream_iterator&) = default; ostream_iterator& operator=(const T& value); ostream_iterator& operator*(); ostream_iterator& operator++(); ostream_iterator& operator++(int); private: basic_ostream<charT,traits>* out_stream = nullptr; // exposition only const charT* delim = nullptr; // exposition only }; }
ostream_iterator(ostream_type& s);
ostream_iterator(ostream_type& s, const charT* delimiter);
ostream_iterator(const ostream_iterator& x);
~ostream_iterator();
ostream_iterator& operator=(const T& value);
ostream_iterator& operator*();
ostream_iterator& operator++();
ostream_iterator& operator++(int);
namespace std { template<class charT, class traits = char_traits<charT>> class istreambuf_iterator { public: using iterator_category = input_iterator_tag; using value_type = charT; using difference_type = typename traits::off_type; using pointer = unspecified; using reference = charT; using char_type = charT; using traits_type = traits; using int_type = typename traits::int_type; using streambuf_type = basic_streambuf<charT,traits>; using istream_type = basic_istream<charT,traits>; class proxy; // exposition only constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel_t) noexcept; istreambuf_iterator(const istreambuf_iterator&) noexcept = default; ~istreambuf_iterator() = default; istreambuf_iterator(istream_type& s) noexcept; istreambuf_iterator(streambuf_type* s) noexcept; istreambuf_iterator(const proxy& p) noexcept; istreambuf_iterator& operator=(const istreambuf_iterator&) noexcept = default; charT operator*() const; istreambuf_iterator& operator++(); proxy operator++(int); bool equal(const istreambuf_iterator& b) const; friend bool operator==(default_sentinel_t s, const istreambuf_iterator& i); friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); friend bool operator!=(default_sentinel_t a, const istreambuf_iterator& b); friend bool operator!=(const istreambuf_iterator& a, default_sentinel_t b); private: streambuf_type* sbuf_; // exposition only }; }
namespace std { template<class charT, class traits> class istreambuf_iterator<charT, traits>::proxy { // exposition only charT keep_; basic_streambuf<charT,traits>* sbuf_; proxy(charT c, basic_streambuf<charT,traits>* sbuf) : keep_(c), sbuf_(sbuf) { } public: charT operator*() { return keep_; } }; }
constexpr istreambuf_iterator() noexcept;
constexpr istreambuf_iterator(default_sentinel_t) noexcept;
istreambuf_iterator(istream_type& s) noexcept;
istreambuf_iterator(streambuf_type* s) noexcept;
istreambuf_iterator(const proxy& p) noexcept;
charT operator*() const
istreambuf_iterator& operator++();
proxy operator++(int);
bool equal(const istreambuf_iterator& b) const;
template<class charT, class traits>
bool operator==(const istreambuf_iterator<charT,traits>& a,
const istreambuf_iterator<charT,traits>& b);
friend bool operator==(default_sentinel_t s, const istreambuf_iterator& i);
friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s);
template<class charT, class traits>
bool operator!=(const istreambuf_iterator<charT,traits>& a,
const istreambuf_iterator<charT,traits>& b);
friend bool operator!=(default_sentinel_t a, const istreambuf_iterator& b);
friend bool operator!=(const istreambuf_iterator& a, default_sentinel_t b);
namespace std { template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator { public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using char_type = charT; using traits_type = traits; using streambuf_type = basic_streambuf<charT,traits>; using ostream_type = basic_ostream<charT,traits>; constexpr ostreambuf_iterator() noexcept = default; ostreambuf_iterator(ostream_type& s) noexcept; ostreambuf_iterator(streambuf_type* s) noexcept; ostreambuf_iterator& operator=(charT c); ostreambuf_iterator& operator*(); ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int); bool failed() const noexcept; private: streambuf_type* sbuf_ = nullptr; // exposition only }; }
ostreambuf_iterator(ostream_type& s) noexcept;
ostreambuf_iterator(streambuf_type* s) noexcept;
ostreambuf_iterator& operator=(charT c);
ostreambuf_iterator& operator*();
ostreambuf_iterator& operator++();
ostreambuf_iterator& operator++(int);
bool failed() const noexcept;
template<class C> constexpr auto begin(C& c) -> decltype(c.begin());
template<class C> constexpr auto begin(const C& c) -> decltype(c.begin());
template<class C> constexpr auto end(C& c) -> decltype(c.end());
template<class C> constexpr auto end(const C& c) -> decltype(c.end());
template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;
template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;
template<class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c)))
-> decltype(std::begin(c));
template<class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c)))
-> decltype(std::end(c));
template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin());
template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());
template<class C> constexpr auto rend(C& c) -> decltype(c.rend());
template<class C> constexpr auto rend(const C& c) -> decltype(c.rend());
template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]);
template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]);
template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);
template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);
template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));
template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));
template<class C> constexpr auto size(const C& c) -> decltype(c.size());
template<class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept;
template<class C> [[nodiscard]] constexpr auto empty(const C& c) -> decltype(c.empty());
template<class T, size_t N> [[nodiscard]] constexpr bool empty(const T (&array)[N]) noexcept;
template<class E> [[nodiscard]] constexpr bool empty(initializer_list<E> il) noexcept;
template<class C> constexpr auto data(C& c) -> decltype(c.data());
template<class C> constexpr auto data(const C& c) -> decltype(c.data());
template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept;
template<class E> constexpr const E* data(initializer_list<E> il) noexcept;