[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:templateconcept R = requires (T i) {typename T::type; {*i} -> std::[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"); }; 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:templaterequires 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)*: templateconcept C = requires(T t, ...) { // error: terminates with an ellipsis t;};templateconcept 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 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 concept C =requires (T a, T b) { a + b; // C 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 struct S;template using Ref = T&; template concept C = requires {typename T::inner; // required nested member nametypename S; // 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; // required alias template substitution, fails if T is voidtypename [:T::r1:]; // fails if T​::​r1 is not a reflection of a typetypename [:T::r2:]; // fails if T​::​r2 is not a reflection of a template Z for which Z 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;}; is equivalent torequires { E1; requires C; E2; requires D;}; (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 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 concept C2 = requires(T x) {{*x} -> std::[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]");}; 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]") is satisfied[.](#compound-2.sentence-3) template 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 concept C = sizeof(U) == 1; template concept D = requires (T t) {requires C;};D 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*]