[expr.prim.req]

# 7 Expressions [[expr]](./#expr)

## 7.5 Primary expressions [[expr.prim]](expr.prim#req)

### 7.5.8 Requires expressions [expr.prim.req]

#### [7.5.8.1](#general) General [[expr.prim.req.general]](expr.prim.req.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3193)

A [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") provides a concise way to express
requirements on template arguments
that can be checked by [name lookup](basic.lookup "6.5 Name lookup [basic.lookup]") or by checking properties of types and expressions[.](#general-1.sentence-1)

[requires-expression:](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")  
requires [*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]")opt [*requirement-body*](#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]")

[requirement-parameter-list:](#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]")  
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") )

[requirement-body:](#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]")  
{ [*requirement-seq*](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]") }

[requirement-seq:](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]")  
[*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]") [*requirement-seq*](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]")opt

[requirement:](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")  
[*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]")  
[*type-requirement*](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]")  
[*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")  
[*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested requirements [expr.prim.req.nested]")

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3228)

A [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") is a prvalue of type bool whose value is described below[.](#general-2.sentence-1)

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3232)

[*Example [1](#general-example-1)*:

A common use of [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")*s* is to define
requirements in concepts such as the one below:template<typename T>concept R = requires (T i) {typename T::type; {*i} -> std::[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<const typename T::type&>; };

A [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") can also be used in a[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")) as a way of writing ad hoc
constraints on template arguments such as the one below:template<typename T>requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }

The first requires introduces the[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"), and the second
introduces the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")[.](#general-3.sentence-3)

â *end example*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3256)

A [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") may introduce local parameters using a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")[.](#general-4.sentence-1)

A local parameter of a [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") shall not have a
default argument[.](#general-4.sentence-2)

The type of such a parameter is determined as specified for
a function parameter in [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#general-4.sentence-3)

These parameters have no linkage, storage, or lifetime; they are only used
as notation for the purpose of defining [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")*s*[.](#general-4.sentence-4)

The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a[*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]") shall not terminate with an ellipsis[.](#general-4.sentence-5)

[*Example [2](#general-example-2)*: template<typename T>concept C = requires(T t, ...) { // error: terminates with an ellipsis t;};template<typename T>concept C2 = requires(T p[2]) {(decltype(p))nullptr; // OK, p has type âpointer to T''}; â *end example*]

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3281)

The substitution of template arguments into a [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") can result in
the formation of invalid types or expressions in the immediate context of
its [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")*s* ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")) or
the violation of the semantic constraints of those [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")*s*[.](#general-5.sentence-1)

In such cases, the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") evaluates to false;
it does not cause the program to be ill-formed[.](#general-5.sentence-2)

The substitution and semantic constraint checking
proceeds in lexical order and stops when a condition that
determines the result of the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") is encountered[.](#general-5.sentence-3)

If substitution (if any) and semantic constraint checking succeed,
the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") evaluates to true[.](#general-5.sentence-4)

[*Note [1](#general-note-1)*:

If a [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") contains invalid types or expressions in
its [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")*s*, and it does not appear within the declaration of a templated
entity, then the program is ill-formed[.](#general-5.sentence-5)

â *end note*]

If the substitution of template arguments into a [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]") would always result in a substitution failure, the program is ill-formed;
no diagnostic required[.](#general-5.sentence-6)

[*Example [3](#general-example-3)*: template<typename T> concept C =requires {new decltype((void)T{}); // ill-formed, no diagnostic required}; â *end example*]

#### [7.5.8.2](#simple) Simple requirements [[expr.prim.req.simple]](expr.prim.req.simple)

[simple-requirement:](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]")  
[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") ;

[1](#simple-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3319)

A [*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]") asserts
the validity of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")[.](#simple-1.sentence-1)

The [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is an unevaluated operand[.](#simple-1.sentence-2)

[*Note [1](#simple-note-1)*:

The enclosing [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") will evaluate to false if substitution of template arguments into the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") fails[.](#simple-1.sentence-3)

â *end note*]

[*Example [1](#simple-example-1)*: template<typename T> concept C =requires (T a, T b) { a + b; // C<T> is true if a + b is a valid expression}; â *end example*]

[2](#simple-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3336)

A [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]") that starts with a requires token
is never interpreted as a [*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]")[.](#simple-2.sentence-1)

[*Note [2](#simple-note-2)*:

This simplifies distinguishing between a [*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]") and a [*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested requirements [expr.prim.req.nested]")[.](#simple-2.sentence-2)

â *end note*]

#### [7.5.8.3](#type) Type requirements [[expr.prim.req.type]](expr.prim.req.type)

[type-requirement:](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]")  
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ;  
typename [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")  
typename [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]")

[1](#type-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3354)

A [*type-requirement*](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]") asserts the validity of a type[.](#type-1.sentence-1)

The component names of a [*type-requirement*](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) and[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") (if any)[.](#type-1.sentence-2)

[*Note [1](#type-note-1)*:

The enclosing [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") will evaluate to false if substitution of template arguments fails[.](#type-1.sentence-3)

â *end note*]

[*Example [1](#type-example-1)*: template<typename T, typename T::type = 0> struct S;template<typename T> using Ref = T&;

template<typename T> concept C = requires {typename T::inner; // required nested member nametypename S<T>; // required valid ([[temp.names]](temp.names "13.3 Names of template specializations")) [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"); fails if T​::​type does not exist as a type// to which 0 can be implicitly convertedtypename Ref<T>; // required alias template substitution, fails if T is voidtypename [:T::r1:]; // fails if T​::​r1 is not a reflection of a typetypename [:T::r2:]<int>; // fails if T​::​r2 is not a reflection of a template Z for which Z<int> is a type}; â *end example*]

[2](#type-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3379)

A [*type-requirement*](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]") that names a class template specialization
does not require that type to be complete ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1 General"))[.](#type-2.sentence-1)

#### [7.5.8.4](#compound) Compound requirements [[expr.prim.req.compound]](expr.prim.req.compound)

[compound-requirement:](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")  
{ [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") } noexceptopt [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")opt ;

[return-type-requirement:](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")  
-> [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")

[1](#compound-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3396)

A [*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") asserts properties
of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E[.](#compound-1.sentence-1)

The [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is an unevaluated operand[.](#compound-1.sentence-2)

Substitution
of template arguments (if any) and verification of
semantic properties proceed in the following order:

- [(1.1)](#compound-1.1)

  Substitution of template arguments (if any)
into the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is performed[.](#compound-1.1.sentence-1)

- [(1.2)](#compound-1.2)

  If the noexcept specifier is present,E shall not be a potentially-throwing expression ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#compound-1.2.sentence-1)

- [(1.3)](#compound-1.3)

  If the [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") is present, then:
  * [(1.3.1)](#compound-1.3.1)

      Substitution of template arguments (if any)
into the [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") is performed[.](#compound-1.3.1.sentence-1)

  * [(1.3.2)](#compound-1.3.2)

      The immediately-declared constraint ([[temp.param]](temp.param "13.2 Template parameters"))
of the [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") for decltype((E)) shall be satisfied[.](#compound-1.3.2.sentence-1)

  [*Example [1](#compound-example-1)*:
  Given concepts C and D,requires {{ E1 } -> C; { E2 } -> D<A1, â¯, An>;}; is equivalent torequires { E1; requires C<decltype((E1))>;
 E2; requires D<decltype((E2)), A1, â¯, An>;}; (including in the case where n is zero)[.](#compound-1.3.sentence-2)
 â *end example*]

[2](#compound-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3442)

[*Example [2](#compound-example-2)*: template<typename T> concept C1 = requires(T x) {{x++};};

The [*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") in C1 requires that x++ is a valid expression[.](#compound-2.sentence-1)

It is equivalent to the [*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]")x++;[.](#compound-2.sentence-2)

template<typename T> concept C2 = requires(T x) {{*x} -> std::[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<typename T::inner>;};

The [*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") in C2 requires that *x is a valid expression,
that typename T​::​inner is a valid type, and
that std​::​[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<decltype((*x)), typename T​::​inner> is satisfied[.](#compound-2.sentence-3)

template<typename T> concept C3 =requires(T x) {{g(x)} noexcept; };

The [*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]") in C3 requires that g(x) is a valid expression and
that g(x) is non-throwing[.](#compound-2.sentence-4)

â *end example*]

#### [7.5.8.5](#nested) Nested requirements [[expr.prim.req.nested]](expr.prim.req.nested)

[nested-requirement:](#nt:nested-requirement "7.5.8.5 Nested requirements [expr.prim.req.nested]")  
requires [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") ;

[1](#nested-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3485)

A [*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested requirements [expr.prim.req.nested]") can be used
to specify additional constraints in terms of local parameters[.](#nested-1.sentence-1)

The [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") shall be satisfied ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))
by the substituted template arguments, if any[.](#nested-1.sentence-2)

Substitution of template arguments into a [*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested requirements [expr.prim.req.nested]") does not result in substitution into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") other than as specified in [[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")[.](#nested-1.sentence-3)

[*Example [1](#nested-example-1)*:

template<typename U> concept C = sizeof(U) == 1;

template<typename T> concept D = requires (T t) {requires C<decltype (+t)>;};D<T> is satisfied if sizeof(decltype (+t)) == 1 ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints"))[.](#nested-1.sentence-4)

â *end example*]
