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 indirectly-readable-impl = requires(const In in) { typename iter_value_t<In>; typename iter_reference_t<In>; typename iter_rvalue_reference_t<In>; { *in } -> same_as<iter_reference_t<In>>; { ranges::iter_move(in) } -> same_as<iter_rvalue_reference_t<In>>; } && common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&> && common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> && common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;
template<class In> concept indirectly_readable = indirectly-readable-impl<remove_cvref_t<In>>;
template<class Out, class T> concept indirectly_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 T> inline constexpr bool is-integer-like = see below; // exposition only template<class T> inline constexpr bool is-signed-integer-like = see below; // exposition only template<class I> concept weakly_incrementable = default_initializable<I> && movable<I> && requires(I i) { typename iter_difference_t<I>; requires is-signed-integer-like<iter_difference_t<I>>; { ++i } -> same_as<I&>; // not required to be equality-preserving i++; // not required to be equality-preserving };
template<class I> concept incrementable = regular<I> && weakly_incrementable<I> && requires(I i) { { i++ } -> same_as<I>; };
template<class I> concept input_or_output_iterator = requires(I i) { { *i } -> can-reference; } && weakly_incrementable<I>;
template<class S, class I>
concept sentinel_for =
semiregular<S> &&
input_or_output_iterator<I> &&
weakly-equality-comparable-with<S, I>; // See [concept.equalitycomparable]
template<class S, class I>
concept sized_sentinel_for =
sentinel_for<S, I> &&
!disable_sized_sentinel_for<remove_cv_t<S>, remove_cv_t<I>> &&
requires(const I& i, const S& s) {
{ s - i } -> same_as<iter_difference_t<I>>;
{ i - s } -> same_as<iter_difference_t<I>>;
};
template<class S, class I>
inline constexpr bool disable_sized_sentinel_for = false;
template<class I> concept input_iterator = input_or_output_iterator<I> && indirectly_readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;
template<class I, class T> concept output_iterator = input_or_output_iterator<I> && indirectly_writable<I, T> && requires(I i, T&& t) { *i++ = std::forward<T>(t); // not required to be equality-preserving };
template<class I> concept forward_iterator = input_iterator<I> && derived_from<ITER_CONCEPT(I), forward_iterator_tag> && incrementable<I> && sentinel_for<I, I>;
template<class I> concept bidirectional_iterator = forward_iterator<I> && derived_from<ITER_CONCEPT(I), bidirectional_iterator_tag> && requires(I i) { { --i } -> same_as<I&>; { i-- } -> same_as<I>; };
template<class I> concept random_access_iterator = bidirectional_iterator<I> && derived_from<ITER_CONCEPT(I), random_access_iterator_tag> && totally_ordered<I> && sized_sentinel_for<I, I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> same_as<I&>; { j + n } -> same_as<I>; { n + j } -> same_as<I>; { i -= n } -> same_as<I&>; { j - n } -> same_as<I>; { j[n] } -> same_as<iter_reference_t<I>>; };
template<class I> concept contiguous_iterator = random_access_iterator<I> && derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> && is_lvalue_reference_v<iter_reference_t<I>> && same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> && requires(const I& i) { { to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>; };