std::ranges::Range
From cppreference.com
Defined in header <ranges>


template< class T > concept Range = __RangeImpl<T&>; // expositiononly definition 
(1)  
// expositiononly helper concept template< class T > 
(2)  
// expositiononly helper concept template< class 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.
Formally, 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 nonmodifying, and
 if the type of ranges::begin(E) models
ForwardIterator
, ranges::begin(E) is equalitypreserving (in other words, forward iterators support multipass algorithms)
ranges::begin(std::forward<T>(t))
and ranges::end(std::forward<T>(t))
do not require implicit expression variations.3) The expositiononly 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.
Formally, 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 expressionequivalent (have the same effect when evaluated, and both or neither are potentiallythrowing, both or neither are constant subexpressions), and
 ranges::end(E) and ranges::end(t) are expressionequivalent, and
 the validity of iterators obtained from the object denoted by E is not tied to the lifetime of that object.