models ` range ` only if

  * ` [ ` [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  E  )  ` , ` [ ranges::  end  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end) (  E  )  ` ) ` denotes a [ range ](/w/cpp/iterator#Ranges "cpp/iterator") , and 
  * both  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  E  )  and  [ ranges::  end  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end) (  E  )  are amortized constant time and do not alter the value of  E  in a manner observable to [ equality-preserving ](/w/cpp/concepts#Equality_preservation "cpp/concepts") expressions, and 
  * if the type of  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  E  )  models [ ` forward_iterator ` ](/w/cpp/iterator/forward_iterator "cpp/iterator/forward iterator") ,  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  E  )  is [ equality-preserving ](/w/cpp/concepts#Equality_preservation "cpp/concepts") (in other words, forward iterators support multi-pass algorithms). 

###  [ [ edit ](/mwiki/index.php?title=cpp/ranges/range&action=edit&section=2
"Edit section: Notes") ]  Notes

A typical ` range ` class only needs to provide two functions:

  1. A member function ` begin() ` whose return type models [ ` input_or_output_iterator ` ](/w/cpp/iterator/input_or_output_iterator "cpp/iterator/input or output iterator") . 
  2. A member function ` end() ` whose return type models [ ` sentinel_for ` ](/w/cpp/iterator/sentinel_for "cpp/iterator/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 ](/w/cpp/language/adl "cpp/language/adl") .

###  [ [ edit ](/mwiki/index.php?title=cpp/ranges/range&action=edit&section=3
"Edit section: Example") ]  Example

Run this code

    
    
    #include <iostream>
    #include <ranges>
    #include <vector>
     
    template<typename T>
    struct range_t : private T
    {
        using T::begin, T::end; /* ... */
    };
    static_assert(std::ranges::range<range_t<[std::vector](http://en.cppreference.com/w/cpp/container/vector)<int>>>);
     
    template<typename T>
    struct scalar_t
    {
        T t {}; /* no begin/end */
    };
    static_assert(not std::ranges::range<scalar_t<int>>);
     
    int main()
    {
        if constexpr (range_t<[std::vector](http://en.cppreference.com/w/cpp/container/vector)<int>> r; std::ranges::range<decltype(r)>)
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << "r is a range\n";
     
        if constexpr (scalar_t<int> s; not std::ranges::range<decltype(s)>)
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << "s is not a range\n";
    }

Output:

    
    
    r is a range
    s is not a range

###  [ [ edit ](/mwiki/index.php?title=cpp/ranges/range&action=edit&section=4
"Edit section: Defect reports") ]  Defect reports

The following behavior-changing defect reports were applied retroactively to
previously published C++ standards.

DR  |  Applied to  |  Behavior as published  |  Correct behavior   
---|---|---|---  
[ LWG 3915 ](https://cplusplus.github.io/LWG/issue3915) |  C++20  |  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  t  )  and  [ ranges::  end  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end) (  t  )    
did not require implicit expression variations  |  removed the   
redundant description  
  
Retrieved from " [
https://en.cppreference.com/mwiki/index.php?title=cpp/ranges/range&oldid=162177
](https://en.cppreference.com/mwiki/index.php?title=cpp/ranges/range&oldid=162177)
"

#####  Navigation

  * [ Support us ](http://www.cppreference.com/support)
  * [ Recent changes ](/w/Special:RecentChanges "A list of recent changes in the wiki \[r\]")
  * [ FAQ ](/w/Cppreference