The *normal form* of an *expression* E is
a constraint that is defined as follows:

- The normal form of a concept-id C<A, A, ..., A> is the normal form of the
*constraint-expression*of C, after substituting A, A, ..., A for C's respective template parameters in the parameter mappings in each atomic constraint.If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.[*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*is valid and results in T::value (with the mapping ) ∨ true (with an empty mapping), despite the expression T::value being ill-formed for a pointer type T.Normalization of C's—*constraint-expression*results in the program being ill-formed, because it would form the invalid type V&* in the parameter mapping.*end example*] - For a
*fold-operator*([expr.prim.fold]) that is either && or ||, the normal form of an expression ( ...*fold-operator*E ) is the normal form of ( E*fold-operator*... ). - For a
*fold-operator*that is either && or ||, the normal form of an expression ( E1*fold-operator*...*fold-operator*E2 ) is the the normal form of- ( E1
*fold-operator*... )*fold-operator*E2 if E1 contains an unexpanded pack, or - E1
*fold-operator*( E2*fold-operator*... ) otherwise.

- ( E1
- The normal form of ( E && ... ) is a fold expanded constraint ([temp.constr.fold]) whose constraint is the normal form of E and whose
*fold-operator*is &&. - The normal form of ( E || ... ) is a fold expanded constraint whose constraint is the normal form of E and whose
*fold-operator*is ||. - The normal form of any other expression E is the atomic constraint whose expression is E and whose parameter mapping is the identity mapping.

[*Note 1*: *end note*]

Normalization of *constraint-expression**s*
is performed
when determining the associated constraints ([temp.constr.constr])
of a declaration
and
when evaluating the value of an *id-expression*
that names a concept specialization ([expr.prim.id]).

— [*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); // #1
template<C3 U> void f2(U); // #2
template<C4 U> void f3(U); // #3

—*end example*]

—