[temp.constr.decl]

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

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

### 13.5.3 Constrained declarations [temp.constr.decl]

[1](#1)

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

A template declaration ([[temp.pre]](temp.pre "13.1 Preamble"))
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")[.](#1.sentence-1)

This allows the specification of constraints for that declaration as
an expression:

[constraint-expression:](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")  
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15 Logical OR operator [expr.log.or]")

[2](#2)

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

Constraints can also be associated with a declaration through the use of[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") or parameter-type-list[.](#2.sentence-1)

Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* that are used to constrain the declaration[.](#2.sentence-2)

[3](#3)

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

A declaration's [*associated constraints*](#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") are defined as follows:

- [(3.1)](#3.1)

  If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s*,
the declaration has no associated constraints[.](#3.1.sentence-1)

- [(3.2)](#3.2)

  Otherwise, if there is a single introduced [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]"),
the associated constraints are the [normal form](temp.constr.normal#def:normal_form,constraint "13.5.4 Constraint normalization [temp.constr.normal]") of that expression[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  Otherwise, the associated constraints are the normal form of a [logicaland expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") whose operands are in the
following order:
  * [(3.3.1)](#3.3.1)

the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")) in
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]"),
in order of appearance, and

  * [(3.3.2)](#3.3.2)

the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") following
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")), and

  * [(3.3.3)](#3.3.3)

the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") in
the parameter-type-list of a function declaration, and

  * [(3.3.4)](#3.3.4)

the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")) of
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#3.3.sentence-1)

The formation of the associated constraints
establishes the order in which constraints are instantiated when checking
for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#3.sentence-2)

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

template<C T> void f1(T);template<typename T> requires C<T> void f2(T);template<typename T> void f3(T) requires C<T>;

The functions f1, f2, and f3 have the associated
constraint C<T>[.](#3.sentence-3)

template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) > 0;

template<C1 T> void f4(T) requires C2<T>;template<typename T> requires C1<T> && C2<T> void f5(T);

The associated constraints of f4 and f5 are C1<T>  â§  C2<T>[.](#3.sentence-4)

template<C1 T> requires C2<T> void f6();template<C2 T> requires C1<T> void f7();

The associated constraints off6 are C1<T>  â§  C2<T>,
and those off7 are C2<T>  â§  C1<T>[.](#3.sentence-5)

â *end example*]

[4](#4)

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

When determining whether a given introduced[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") C1 of a declaration
in an instantiated specialization of a templated class
is equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") C2 of a declaration
outside the class body,C1 is instantiated[.](#4.sentence-1)

If the instantiation results in an invalid expression,
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are not equivalent[.](#4.sentence-2)

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

This can happen when determining which member template is specialized
by an explicit specialization declaration[.](#4.sentence-3)

â *end note*]

[*Example [2](#example-2)*: template <class T> concept C = true;template <class T> struct A {template <class U> U f(U) requires C<typename T::type>; // #1template <class U> U f(U) requires C<T>; // #2};

template <> template <class U> U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2

Substituting int for T in C<typename T​::​type> produces an invalid expression, so the specialization does not match #1[.](#4.sentence-4)

Substituting int for T in C<T> produces C<int>,
which is equivalent to the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") for the specialization,
so it does match #2[.](#4.sentence-5)

â *end example*]
