std::ranges::range

From cppreference.com
< cpp‎ | ranges
 
 
 
Defined in header <ranges>
template< class T >
concept range = __RangeImpl<T&>; // exposition-only definition
(1)
// exposition-only helper concept

template< class T >
concept __RangeImpl = requires(T&& t) {
  ranges::begin(std::forward<T>(t)); // equality-preserving for forward iterators
  ranges::end  (std::forward<T>(t));

};
(2)
// exposition-only helper concept

template< class T >

concept __ForwardingRange = ranges::range<T> && __RangeImpl<T>;
(3)
1) The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
3) The exposition-only concept __ForwardingRange defines the requirements of a range such that a function can take it by value and return iterators obtained from it without danger of dangling.

Semantic requirements

1) Given an expression E such that decltype((E)) is T, T models range only if
  • [ranges::begin(E), ranges::end(E)) denotes a range, and
  • both ranges::begin(E) and ranges::end(E) are amortized constant time and non-modifying, and
  • if the type of ranges::begin(E) models forward_iterator, ranges::begin(E) is equality-preserving (in other words, forward iterators support multi-pass algorithms)
Note: In the exposition-only definition above, the required expressions ranges::begin(std::forward<T>(t)) and ranges::end(std::forward<T>(t)) do not require implicit expression variations.
3) Given an expression E such that decltype((E)) is T and an lvalue t that denotes the same object as E, T models __ForwardingRange only if
  • ranges::begin(E) and ranges::begin(t) are expression-equivalent, and
  • ranges::end(E) and ranges::end(t) are expression-equivalent, and
  • the validity of iterators obtained from the object denoted by E is not tied to the lifetime of that object.

Expression-equivalent

Expression e is expression-equivalent to expression f, if e and f have the same effects, either are both potentially-throwing or are both not potentially-throwing (i.e. noexcept(e) == noexcept(f)), and either are both constant subexpressions or are both not constant subexpressions.