.com/w/cpp/ranges-ranges-placeholder/begin) (  t  )  ==  [ ranges::  end  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end) (  t  )  )  , if that expression is valid and  decltype  (  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin) (  t  )  )  models  [ std::forward_iterator ](/w/cpp/iterator/forward_iterator "cpp/iterator/forward iterator") . 

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

###  Customization point objects

The name ` ranges::empty ` 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 ` ___empty_fn_ ` .

All instances of ` ___empty_fn_ ` are equal. The effects of invoking different
instances of type ` ___empty_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::empty ` 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::empty ` above, ` ___empty_fn_ `
models  

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

Otherwise, no function call operator of ` ___empty_fn_ ` participates in
overload resolution.

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

Run this code

    
    
    #include <iostream>
    #include <ranges>
    #include <vector>
     
    template<std::[ranges::input_range](http://en.cppreference.com/w/cpp/ranges/input_range) R>
    void print(char id, R&& r)
    {
        if (std::ranges::empty(r))
        {
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << '\t' << id << ") Empty\n";
            return;
        }
     
        [std::cout](http://en.cppreference.com/w/cpp/io/cout) << '\t' << id << ") Elements:";
        for (const auto& element : r)
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << ' ' << element;
        [std::cout](http://en.cppreference.com/w/cpp/io/cout) << '\n';
    }
     
    int main()
    {
        {
            auto v = [std::vector](http://en.cppreference.com/w/cpp/container/vector)<int>{1, 2, 3};
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << "(1) ranges::empty uses std::vector::empty:\n";
            print('a', v);
     
            v.clear();
            print('b', v);
        }
        {
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << "(2) ranges::empty uses ranges::size(initializer_list):\n";
            auto il = {7, 8, 9};
            print('a', il);
     
            print('b', [std::initializer_list](http://en.cppreference.com/w/cpp/utility/initializer_list)<int>{});
        }
        {
            [std::cout](http://en.cppreference.com/w/cpp/io/cout) << "(2) ranges::empty on a raw array uses ranges::size:\n";
            int array[] = {4, 5, 6}; // array h