[temp.constr.constr] # 13 Templates [[temp]](./#temp) ## 13.5 Template constraints [[temp.constr]](temp.constr#constr) ### 13.5.2 Constraints [temp.constr.constr] #### [13.5.2.1](#general) General [[temp.constr.constr.general]](temp.constr.constr.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610) A [*constraint*](#def:constraint "13.5.2.1 General [temp.constr.constr.general]") is a sequence of logical operations and operands that specifies requirements on template arguments[.](#general-1.sentence-1) The operands of a logical operation are constraints[.](#general-1.sentence-2) There are five different kinds of constraints: - [(1.1)](#general-1.1) conjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2 Logical operations")), - [(1.2)](#general-1.2) disjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2 Logical operations")), - [(1.3)](#general-1.3) atomic constraints ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints")), - [(1.4)](#general-1.4) concept-dependent constraints ([[temp.constr.concept]](#temp.constr.concept "13.5.2.4 Concept-dependent constraints")), and - [(1.5)](#general-1.5) fold expanded constraints ([[temp.constr.fold]](#temp.constr.fold "13.5.2.5 Fold expanded constraint"))[.](#general-1.sentence-3) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623) In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9 Template instantiation and specialization")), its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#general-2.sentence-1) [*Note [1](#general-note-1)*: Forming the name of a specialization of a class template, a variable template, or an alias template ([[temp.names]](temp.names "13.3 Names of template specializations")) requires the satisfaction of its constraints[.](#general-2.sentence-2) [Overload resolution](over.match.viable "12.2.3 Viable functions [over.match.viable]") requires the satisfaction of constraints on functions and function templates[.](#general-2.sentence-3) — *end note*] #### [13.5.2.2](#temp.constr.op) Logical operations [[temp.constr.op]](temp.constr.op) [1](#temp.constr.op-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640) There are two binary logical operations on constraints: conjunction and disjunction[.](#temp.constr.op-1.sentence-1) [*Note [1](#temp.constr.op-note-1)*: These logical operations have no corresponding C++ syntax[.](#temp.constr.op-1.sentence-2) For the purpose of exposition, conjunction is spelled using the symbol ∧ and disjunction is spelled using the symbol ∨ [.](#temp.constr.op-1.sentence-3) The operands of these operations are called the left and right operands[.](#temp.constr.op-1.sentence-4) In the constraint A ∧ B,A is the left operand, and B is the right operand[.](#temp.constr.op-1.sentence-5) — *end note*] [2](#temp.constr.op-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653) A [*conjunction*](#def:conjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two operands[.](#temp.constr.op-2.sentence-1) To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2 Logical operations [temp.constr.op]"), the satisfaction of the first operand is checked[.](#temp.constr.op-2.sentence-2) If that is not satisfied, the conjunction is not satisfied[.](#temp.constr.op-2.sentence-3) Otherwise, the conjunction is satisfied if and only if the second operand is satisfied[.](#temp.constr.op-2.sentence-4) [3](#temp.constr.op-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664) A [*disjunction*](#def:disjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two operands[.](#temp.constr.op-3.sentence-1) To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2 Logical operations [temp.constr.op]"), the satisfaction of the first operand is checked[.](#temp.constr.op-3.sentence-2) If that is satisfied, the disjunction is satisfied[.](#temp.constr.op-3.sentence-3) Otherwise, the disjunction is satisfied if and only if the second operand is satisfied[.](#temp.constr.op-3.sentence-4) [4](#temp.constr.op-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676) [*Example [1](#temp.constr.op-example-1)*: templateconstexpr bool get_value() { return T::value; }templaterequires (sizeof(T) > 1) && (get_value())void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value()void f(int); f('a'); // OK, calls f(int) In the satisfaction of the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied; the second operand is not checked for satisfaction[.](#temp.constr.op-4.sentence-1) — *end example*] [5](#temp.constr.op-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695) [*Note [2](#temp.constr.op-note-2)*: A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")) is an atomic constraint; the negation operator is not treated as a logical operation on constraints[.](#temp.constr.op-5.sentence-1) As a result, distinct negation [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints")[.](#temp.constr.op-5.sentence-2) Furthermore, if substitution to determine whether an atomic constraint is satisfied ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints")) encounters a substitution failure, the constraint is not satisfied, regardless of the presence of a negation operator[.](#temp.constr.op-5.sentence-3) [*Example [2](#temp.constr.op-example-2)*: template concept sad = false; template int f1(T) requires (!sad);template int f1(T) requires (!sad) && true;int i1 = f1(42); // ambiguous, !sad atomic constraint expressions ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")template concept not_sad = !sad;template int f2(T) requires not_sad;template int f2(T) requires not_sad && true;int i2 = f2(42); // OK, !sad atomic constraint expressions both come from not_sadtemplate int f3(T) requires (!sad);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate concept sad_nested_type = sad;template int f4(T) requires (!sad_nested_type);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type Here,requires (!sad) requires that there is a nested type that is not sad, whereasrequires (!sad_nested_type) requires that there is no sad nested type[.](#temp.constr.op-5.sentence-4) — *end example*] — *end note*] #### [13.5.2.3](#temp.constr.atomic) Atomic constraints [[temp.constr.atomic]](temp.constr.atomic) [1](#temp.constr.atomic-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738) An [*atomic constraint*](#def:constraint,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]") is formed from an expression E and a mapping from the template parameters that appear within E to template arguments that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#temp.constr.atomic-1.sentence-1) [*Note [1](#temp.constr.atomic-note-1)*: Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#temp.constr.atomic-1.sentence-2) E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical OR operator [expr.log.or]")[.](#temp.constr.atomic-1.sentence-3) — *end note*] [2](#temp.constr.atomic-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753) Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to those mapped by the parameter mappings of the expression, a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are the targets of the parameter mapping of e2[.](#temp.constr.atomic-2.sentence-1) [*Note [2](#temp.constr.atomic-note-2)*: The comparison of parameter mappings of atomic constraints operates in a manner similar to that of declaration matching with alias template substitution ([[temp.alias]](temp.alias "13.7.8 Alias templates"))[.](#temp.constr.atomic-2.sentence-2) [*Example [1](#temp.constr.atomic-example-1)*: template constexpr bool Atomic = true;template concept C = Atomic;template concept Add1 = C;template concept AddOne = C;template void f()requires Add1<2 * M>;template int f()requires AddOne<2 * M> && true; int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic// with mapping similar to N↦2 * M + 1template struct WrapN;template using Add1Ty = WrapN;template using AddOneTy = WrapN;template void g(Add1Ty<2 * M> *);template void g(AddOneTy<2 * M> *); void h() { g<0>(nullptr); // OK, there is only one g} — *end example*] As specified in [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"), if the validity or meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-2.sentence-3) [*Example [2](#temp.constr.atomic-example-2)*: template void f2()requires Add1<2 * N>;template int f2()requires Add1 && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} — *end example*] — *end note*] [3](#temp.constr.atomic-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819) To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]"), the parameter mapping and template arguments are first substituted into its expression[.](#temp.constr.atomic-3.sentence-1) If substitution results in an invalid type or expression in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")), the constraint is not satisfied[.](#temp.constr.atomic-3.sentence-2) Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]") is performed if necessary, and E shall be a constant expression of type bool[.](#temp.constr.atomic-3.sentence-3) The constraint is satisfied if and only if evaluation of E results in true[.](#temp.constr.atomic-3.sentence-4) If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-3.sentence-5) [*Example [3](#temp.constr.atomic-example-3)*: template concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate struct S {constexpr operator bool() const { return true; }}; template requires (S{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match — *end example*] #### [13.5.2.4](#temp.constr.concept) Concept-dependent constraints [[temp.constr.concept]](temp.constr.concept) [1](#temp.constr.concept-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857) A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]") CD is an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") names a dependent concept named C[.](#temp.constr.concept-1.sentence-1) [2](#temp.constr.concept-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862) To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]"), the parameter mapping and template arguments are first substituted into C[.](#temp.constr.concept-2.sentence-1) If substitution results in an invalid concept-id in the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")), the constraint is not satisfied[.](#temp.constr.concept-2.sentence-2) Otherwise, let CI′ be the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4 Constraint normalization")) of the concept-id after substitution of C[.](#temp.constr.concept-2.sentence-3) [*Note [1](#temp.constr.concept-note-1)*: Normalization of CI might be ill-formed; no diagnostics is required[.](#temp.constr.concept-2.sentence-4) — *end note*] [3](#temp.constr.concept-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877) To form CI′′, each appearance of C's template parameters in the parameter mappings of the atomic constraints (including concept-dependent constraints) in CI′ is substituted with their respective arguments from the parameter mapping of CD and the arguments of CI[.](#temp.constr.concept-3.sentence-1) [4](#temp.constr.concept-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886) CD is satisfied if CI′′ is satisfied[.](#temp.constr.concept-4.sentence-1) [*Note [2](#temp.constr.concept-note-2)*: Checking whether CI′′ is satisfied can lead to further normalization of concept-dependent constraints[.](#temp.constr.concept-4.sentence-2) — *end note*] [*Example [1](#temp.constr.concept-example-1)*: templateconcept C = true; template concept CC>concept D = CC; template concept CT, template concept> concept CU>int f() requires CU;int i = f(); In this example, the associated constraints of f consist of a concept-dependent constraint whose expression is the concept-id CU with the mappingU↦U,CT↦CT,CU↦CU[.](#temp.constr.concept-4.sentence-3) The result of substituting D into this expression is D[.](#temp.constr.concept-4.sentence-4) We consider the normal form of the resulting concept-id, which is CC with the mappingT↦U,CC↦CT[.](#temp.constr.concept-4.sentence-5) By recursion, C is substituted into CC, and the result is normalized to the atomic constraint true, which is satisfied[.](#temp.constr.concept-4.sentence-6) — *end example*] #### [13.5.2.5](#temp.constr.fold) Fold expanded constraint [[temp.constr.fold]](temp.constr.fold) [1](#temp.constr.fold-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920) A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") which can either be && or ||[.](#temp.constr.fold-1.sentence-1) A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#temp.constr.fold-1.sentence-2) Let N be the number of elements in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#temp.constr.fold-1.sentence-3) [2](#temp.constr.fold-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928) A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is && is satisfied if it is a valid pack expansion and if N=0 or if for each i where 0≤i0, and if for i where 0≤i