std::ranges::range(3)

NAME
std::ranges::range - std::ranges::range

Synopsis
   Defined in header <ranges>
   template< class T >
   concept range = requires( T& t ) {
       ranges::begin(t); // equality-preserving for forward iterators (since C++20)
       ranges::end (t);
   };
   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.

Notes
   A typical range class only needs to provide two functions:
    1. A member function begin() whose return type models input_or_output_iterator.
    2. A member function end() whose return type models sentinel_for<It>, where It is
       the return type of begin().
   Alternatively, they can be non-member functions, to be found by argument-dependent
   lookup.

Example
 #include <ranges>
 // A minimum range
 struct SimpleRange
 {
     int* begin();
     int* end();
 };
 static_assert(std::ranges::range<SimpleRange>);
 // not a range: no begin/end
 struct NotRange
 {
     int t {};
 };
 static_assert(!std::ranges::range<NotRange>);
 // not a range: begin does not return an input_or_output_iterator
 struct NotRange2
 {
     void* begin();
     int* end();
 };
 static_assert(!std::ranges::range<NotRange2>);
   Defect reports
   The following behavior-changing defect reports were applied retroactively to
   previously published C++ standards.
      DR Applied to Behavior as published Correct behavior
                       ranges::begin(t) and ranges::end(t) removed the
   LWG 3915 C++20 did not require implicit expression redundant description
                       variations