>> &&  
[ ranges::  sized_range  ](http://en.cppreference.com/w/cpp/ranges/sized_range) < __maybe_const  < Const, Vs  >> )  )  ;  |  (3)  |  (  exposition only*  )   
template  < class  R  >  
concept __cartesian_product_common_arg  =  
[ ranges::  common_range
](http://en.cppreference.com/w/cpp/ranges/common_range) < R  > ||  
(  [ ranges::  sized_range  ](http://en.cppreference.com/w/cpp/ranges/sized_range) < R  > && [ ranges::  random_access_range  ](http://en.cppreference.com/w/cpp/ranges/random_access_range) < R  > )  ;  |  (4)  |  (  exposition only*  )   
template  < bool  Const,  class  First,  class  ...  Vs  >  
concept __cartesian_product_is_bidirectional  =  
(  [ ranges::  bidirectional_range
](http://en.cppreference.com/w/cpp/ranges/bidirectional_range) < __maybe_const
< Const, First  >> && ...  &&  
(  [ ranges::  bidirectional_range
](http://en.cppreference.com/w/cpp/ranges/bidirectional_range) < __maybe_const
< Const, Vs  >> &&  
__cartesian_product_common_arg  < __maybe_const  < Const, Vs  >> )  )  ;  |  (5)  |  (  exposition only*  )   
template  < class  First,  class  ...  Vs  >  
concept __cartesian_product_is_common  =  
__cartesian_product_common_arg  < First  > ;  |  (6)  |  (  exposition only*  )   
template  < class  ...  Vs  >  
concept __cartesian_product_is_sized  =  
(  [ ranges::  sized_range  ](http://en.cppreference.com/w/cpp/ranges/sized_range) < Vs  > && ...  )  ;  |  (7)  |  (  exposition only*  )   
template  < bool  Const,  template  < class  > class  FirstSent,  class
First,  class  ...  Vs  >  
concept __cartesian_is_sized_sentinel  =  
(  ranges  ::  sized_sentinel_for  < FirstSent  < __maybe_const  < Const,
First  >> ,  
[ ranges::  iterator_t  ](http://en.cppreference.com/w/cpp/ranges-ranges-
placeholder/iterator_t) < __maybe_const  < Const, First  >>> && ...  &&  
(  [ ranges::  sized_range
](http://en.cppreference.com/w/cpp/ranges/sized_range) < __maybe_const  <
Const, Vs  >> &&  
ranges  ::  sized_sentinel_for  < iterator_t  < __maybe_const  < Const, Vs  >>
,  
[ ranges::  iterator_t  ](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/iterator_t) < __maybe_const  < Const, Vs  >>> )  )  ;  |  (8)  |  (  exposition only*  )   
Helper function templates  |  |   
template  < __cartesian_product_common_arg R  >  
constexpr  auto  __cartesian_common_arg_end  (  R  & r  )  {  
if  constexpr  (  [ ranges::  common_range
](http://en.cppreference.com/w/cpp/ranges/common_range) < R  > )  
return  [ ranges::  end  ](http://en.cppreference.com/w/cpp/ranges-ranges-
placeholder/end) (  r  )  ;  
else  
return  [ ranges::  begin  ](http://en.cppreference.com/w/cpp/ranges-ranges-
placeholder/begin) (  r  )  \+  [ ranges::  distance
](http://en.cppreference.com/w/cpp/iterator/ranges/distance) (  r  )  ;  
}  |  (9)  |  (  exposition only*  )   
|  |   
  
1)  ` cartesian_product_view ` is a range adaptor that takes _n_ [ ` view ` s
](/w/cpp/ranges/view "cpp/ranges/view") , where _n > 0 _ , and produces a [ `
view ` ](/w/cpp/ranges/view "cpp/ranges/view") of tuples calculated by the [
n-ary cartesian product
](https://en.wikipedia.org/wiki/Cartesian_product#n-ary_Cartesian_product
"enwiki:Cartesian product") of the provided ranges. The size of produced view
is a multiple of sizes of provided ranges, while each element is a tuple (of
references) of the size _n_ .

2)  ` views::cartesian_product ` is a customization point object.

  * When calling with no argument,  views  ::  cartesian_product  (  )  is [ expression-equivalent ](/w/cpp/language/expressions#Expression-equivalence "cpp/language/expressions") to  [ views::  single  ](http://en.cppreference.com/w/cpp/ranges/single_view) (  [ std::  tuple  ](http://en.cppreference.com/w/cpp/utility/tuple) (  )  )  . 
  * Otherwise,  views  ::  cartesian_product  (  rs...  )  is [ expression-equivalent ](/w/cpp/language/expressions#Expression-equivalence "cpp/language/expressions") to  ranges  ::  cartesian_product_view  < [ views::  all_t  ](ht