Files
2025-10-25 03:02:53 +03:00

130 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.1Preamble"))
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")[.](#1.sentence-1)
This allows the specification of constraints for that declaration as
an expression:
[constraint-expression:](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15Logical 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.2Template parameters[temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") or parameter-type-list[.](#2.sentence-1)
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained 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.3Constrained declarations[temp.constr.decl]") are defined as follows:
- [(3.1)](#3.1)
If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained 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.3Constrained declarations[temp.constr.decl]"),
the associated constraints are the [normal form](temp.constr.normal#def:normal_form,constraint "13.5.4Constraint 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.14Logical 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.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")) in
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"),
in order of appearance, and
* [(3.3.2)](#3.3.2)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") following
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")), and
* [(3.3.3)](#3.3.3)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template 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.3Constrained declarations[temp.constr.decl]") introduced by
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators")) of
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#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.2Constraints"))[.](#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.3Constrained 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.2Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained 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.3Constrained 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.3Constrained declarations[temp.constr.decl]") for the specialization,
so it does match #2[.](#4.sentence-5)
— *end example*]