[temp.constr.normal]

# 13 Templates [[temp]](./#temp)

## 13.5 Template constraints [[temp.constr]](temp.constr#normal)

### 13.5.4 Constraint normalization [temp.constr.normal]

[1](#1)

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

The [*normal form*](#def:normal_form,constraint "13.5.4 Constraint normalization [temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E is
a [constraint](temp.constr.constr#def:constraint "13.5.2 Constraints [temp.constr.constr]") that is defined as follows:

- [(1.1)](#1.1)

  The normal form of an expression ( E ) is
the normal form of E[.](#1.1.sentence-1)

- [(1.2)](#1.2)

  The normal form of an expression E1 || E2 is
the [disjunction](temp.constr.op#def:disjunction "13.5.2.2 Logical operations [temp.constr.op]") of
the normal forms of E1 and E2[.](#1.2.sentence-1)

- [(1.3)](#1.3)

  The normal form of an expression E1 && E2 is the conjunction of
the normal forms of E1 and E2[.](#1.3.sentence-1)

- [(1.4)](#1.4)

  For a concept-id C<A1, A2, …, An> termed CI:
  * [(1.4.1)](#1.4.1)

      If C names a dependent concept,
the normal form of CI is a concept-dependent constraint
whose concept-id is CI and
whose parameter mapping is the identity mapping[.](#1.4.1.sentence-1)

  * [(1.4.2)](#1.4.2)

      Otherwise, to form CE,
any non-dependent concept template argument Ai is substituted into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") of C[.](#1.4.2.sentence-1)
      If any such substitution results in an invalid concept-id,
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-2)
      The normal form of CI is the result of substituting,
in the normal form N of CE,
appearances of C's template parameters
in the parameter mappings of the atomic constraints in N with their respective arguments from C[.](#1.4.2.sentence-3)
      If any such substitution results in an invalid type or expression,
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-4)

  [*Example [1](#example-1)*: template<typename T> concept A = T::value || true;template<typename U> concept B = A<U*>;template<typename V> concept C = B<V&>;
   Normalization of B's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") is valid and results inT​::​value (with the mapping Tâ¦U*) â¨ true (with an empty mapping),
despite the expression T​::​value being ill-formed
for a pointer type T[.](#1.4.sentence-2)
  Normalization of C's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") results in the program being ill-formed,
because it would form the invalid type V&* in the parameter mapping[.](#1.4.sentence-3)
 â *end example*]

- [(1.5)](#1.5)

  For a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold expressions"))
that is either && or ||:
  * [(1.5.1)](#1.5.1)

      The normal form of an expression ( ... Op E ) is the normal form of ( E Op ... )[.](#1.5.1.sentence-1)

  * [(1.5.2)](#1.5.2)

      The normal form of an expression ( E1 Op ... Op E2 ) is the normal form of
    +
          [(1.5.2.1)](#1.5.2.1)
( E1 Op ... ) Op E2 if E1 contains an unexpanded pack, or

    +
          [(1.5.2.2)](#1.5.2.2)
E1 Op ( E2 Op ... ) otherwise[.](#1.5.2.sentence-1)

  * [(1.5.3)](#1.5.3)

      The normal form of an expression F of the form ( E Op ... ) is as follows:  
       If E contains an unexpanded concept template parameter pack,
 it shall not contain an unexpanded template parameter pack of another kind[.](#1.5.3.sentence-2)
      Let Eâ² be the normal form of E[.](#1.5.3.sentence-3)

    +
          [(1.5.3.1)](#1.5.3.1)
          If E contains
 an unexpanded concept template parameter pack Pk that
 has corresponding template arguments in
 the parameter mapping of any atomic constraint
 (including concept-dependent constraints) of Eâ²,
 the number of arguments specified for all such Pk shall be the same number N[.](#1.5.3.1.sentence-1)
          The normal form of F is the normal form of E0 Op  Op ENâ1 after substituting in Ei the respective ith concept argument of each Pk[.](#1.5.3.1.sentence-2)
          If any such substitution results in an invalid type or expression,
 the program is ill-formed; no diagnostic is required[.](#1.5.3.1.sentence-3)

    +
          [(1.5.3.2)](#1.5.3.2)
          Otherwise,
 the normal form of F is
 a fold expanded constraint ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold expanded constraint")) whose
 constraint is Eâ² and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is Op[.](#1.5.3.2.sentence-1)

- [(1.6)](#1.6)

  The normal form of any other expression E is
the atomic constraint
whose expression is E and
whose parameter mapping is the identity mapping[.](#1.6.sentence-1)

[2](#2)

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

The process of obtaining the normal form of a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#2.sentence-1)

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

Normalization of [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* is performed
when determining the associated constraints ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
of a declaration
and
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5 Names"))[.](#2.sentence-2)

â *end note*]

[3](#3)

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

[*Example [2](#example-2)*: template<typename T> concept C1 = sizeof(T) == 1;template<typename T> concept C2 = C1<T> && 1 == 2;template<typename T> concept C3 = requires { typename T::type; };template<typename T> concept C4 = requires (T x) { ++x; };

template<C2 U> void f1(U); // #1template<C3 U> void f2(U); // #2template<C4 U> void f3(U); // #3

The associated constraints of #1 aresizeof(T) == 1 (with mapping Tâ¦U)  â§  1 == 2[.](#3.sentence-1)

  


The associated constraints of #2 arerequires { typename T​::​type; } (with mapping Tâ¦U)[.](#3.sentence-2)

  


The associated constraints of #3 arerequires (T x) { ++x; } (with mapping Tâ¦U)[.](#3.sentence-3)

â *end example*]

[*Example [3](#example-3)*: template<typename T>concept C = true;template<typename T, template<typename> concept CT>concept CC = CT<T>;

template<typename U, template<typename, template<typename> concept> concept CT>void f() requires CT<U*, C>;template<typename U>void g() requires CC<U*, C>;

The normal form of the associated constraints of f is
the concept-dependent constraint CT<T, C>[.](#3.sentence-4)

  


The normal form of the associated constraints of g is
the atomic constraint true[.](#3.sentence-5)

â *end example*]

[*Example [4](#example-4)*: template<typename T>concept A = true;template<typename T>concept B = A<T> && true; // B subsumes Atemplate<typename T>concept C = true;template<typename T>concept D = C<T> && true; // D subsumes Ctemplate<typename T, template<typename> concept... CTs>concept all_of = (CTs<T> && ...);

template<typename T> requires all_of<T, A, C>constexpr int f(T) { return 1; } // #1template<typename T> requires all_of<T, B, D>constexpr int f(T) { return 2; } // #2static_assert(f(1) == 2); // ok

The normal form of all_of<T, A, C> is
the conjunction of the normal forms of A<T> and C<T>[.](#3.sentence-6)

  


Similarly, the normal form of all_of<T, B, D> is
the conjunction of the normal forms of B<T> and D<T>[.](#3.sentence-7)

  


#2 therefore is more constrained than #1[.](#3.sentence-8)

â *end example*]

[*Example [5](#example-5)*: template<typename T, template<typename> concept>struct wrapper {};

template<typename... T, template<typename> concept... CTs>int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains// different kinds of template parameters â *end example*]
