[ std::  remove_all_extents_t
](http://en.cppreference.com/w/cpp/types/remove_all_extents) < [ std::
remove_reference_t  ](http://en.cppreference.com/w/cpp/types/remove_reference)
< T  >> is incomplete, then the call to ` ranges::rend ` is ill-formed, no
diagnostic required.

If the argument is an lvalue or  [ ranges::  enable_borrowed_range
](http://en.cppreference.com/w/cpp/ranges/borrowed_range) < [ std::
remove_cv_t  ](http://en.cppreference.com/w/cpp/types/remove_cv) < T  >> is
true  , then a call to ` ranges::rend ` is [ expression-equivalent
](/w/cpp/language/expressions#Expression-equivalence
"cpp/language/expressions") to:

  1. [ ` _decay-copy_ ` ](/w/cpp/standard_library/decay-copy "cpp/standard library/decay-copy") (  t.  rend  (  )  )  (until C++23)  auto  (  t.  rend  (  )  )  (since C++23)  , if that expression is valid and its type models  [ std::  sentinel_for  ](http://en.cppreference.com/w/cpp/iterator/sentinel_for) < decltype  (  [ ranges::  rbegin  ](http://en.cppreference.com/w/cpp/ranges/rbegin) (  [ std::  declval  ](http://en.cppreference.com/w/cpp/utility/declval) < T  > (  )  )  )  > . 
  2. Otherwise,  [ ` _decay-copy_ ` ](/w/cpp/standard_library/decay-copy "cpp/standard library/decay-copy") (  rend  (  t  )  )  (until C++23)  auto  (  rend  (  t  )  )  (since C++23)  , if ` T ` is a class or enumeration type, that expression is valid and its type models  [ std::  sentinel_for  ](http://en.cppreference.com/w/cpp/iterator/sentinel_for) < decltype  (  [ ranges::  rbegin  ](http://en.cppreference.com/w/cpp/ranges/rbegin) (  [ std::  declval  ](http://en.cppreference.com/w/cpp/utility/declval) < T  > (  )  )  )  > , where the meaning of ` rend ` is established as if by performing [ argument-dependent lookup ](/w/cpp/language/adl "cpp/language/adl") only. 
  3. Otherwise,  [ std::  make_reverse_iterator  ](http://en.cppreference.com/w/cpp/iterator/make_reverse_iterator) (  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  t  )  )  if both  [ 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  )  are valid expressions, have the same type, and that type models  [ std::bidirectional_iterator ](/w/cpp/iterator/bidirectional_iterator "cpp/iterator/bidirectional iterator") . 

In all other cases, a call to ` ranges::rend ` is ill-formed, which can result
in [ substitution failure ](/w/cpp/language/sfinae "cpp/language/sfinae") when
ranges  ::  rend  (  t  )  appears in the immediate context of a template
instantiation.

##  Contents

  * 1  Customization point objects 
  * 2  Notes 
  * 3  Example 
  * 4  Defect reports 
  * 5  See also 

  
---  
  
###  Customization point objects

The name ` ranges::rend ` denotes a _customization point object_ , which is a
const [ function object ](/w/cpp/named_req/FunctionObject "cpp/named
req/FunctionObject") of a [ literal ](/w/cpp/named_req/LiteralType "cpp/named
req/LiteralType") [ ` semiregular ` ](/w/cpp/concepts/semiregular
"cpp/concepts/semiregular") class type. For exposition purposes, the cv-
unqualified version of its type is denoted as ` ___rend_fn_ ` .

All instances of ` ___rend_fn_ ` are equal. The effects of invoking different
instances of type ` ___rend_fn_ ` on the same arguments are equivalent,
regardless of whether the expression denoting the instance is an lvalue or
rvalue, and is const-qualified or not (however, a volatile-qualified instance
is not required to be invocable). Thus, ` ranges::rend ` can be copied freely
and its copies can be used interchangeably.

Given a set of types ` Args... ` , if  [ std::  declval
](http://en.cppreference.com/w/cpp/utility/declval) < Args  > (  )  ...  meet
the requirements for arguments to ` ranges::rend ` above, ` ___rend_fn_ `
models  

  * [ std::  invocable  ](http://en.cppreference.com/w/cpp/concepts/invocable) < __rend_fn, Args...  >