24 Ranges library [ranges]

24.4 Range requirements [range.req]

24.4.2 Ranges [range.range]

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.
template<class T> concept range = requires(T& t) { ranges::begin(t); // sometimes equality-preserving (see below) ranges::end(t); };
The required expressions ranges​::​begin(t) and ranges​::​end(t) of the range concept do not require implicit expression variations ([concepts.equality]).
Given an expression t such that decltype((t)) is T&, T models range only if
  • [ranges​::​begin(t), ranges​::​end(t)) denotes a range ([iterator.requirements.general]),
  • both ranges​::​begin(t) and ranges​::​end(t) are amortized constant time and non-modifying, and
  • if the type of ranges​::​begin(t) models forward_­iterator, ranges​::​begin(t) is equality-preserving.
[Note 1:
Equality preservation of both ranges​::​begin and ranges​::​end enables passing a range whose iterator type models forward_­iterator to multiple algorithms and making multiple passes over the range by repeated calls to ranges​::​begin and ranges​::​end.
Since ranges​::​begin is not required to be equality-preserving when the return type does not model forward_­iterator, it is possible for repeated calls to not return equal values or to not be well-defined.
β€” end note]
template<class T> concept borrowed_­range = range<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
Given an expression E such that decltype((E)) is T, T models borrowed_­range only if the validity of iterators obtained from the object denoted by E is not tied to the lifetime of that object.
[Note 2:
Since the validity of iterators is not tied to the lifetime of an object whose type models borrowed_­range, a function can accept arguments of such a type by value and return iterators obtained from it without danger of dangling.
β€” end note]
template<class> inline constexpr bool enable_borrowed_range = false;
Remarks: Pursuant to [namespace.std], users may specialize enable_­borrowed_­range for cv-unqualified program-defined types.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.
[Example 1:
Each specialization S of class template subrange ([range.subrange]) models borrowed_­range because
  • enable_­borrowed_­range<S> is specialized to have the value true, and
  • S's iterators do not have validity tied to the lifetime of an S object because they are β€œborrowed” from some other range.
β€” end example]