tmp/tmpd6rku3uq/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
|
| 2 |
+
|
| 3 |
+
A template declaration [[temp.pre]] or templated function declaration
|
| 4 |
+
[[dcl.fct]] can be constrained by the use of a *requires-clause*. This
|
| 5 |
+
allows the specification of constraints for that declaration as an
|
| 6 |
+
expression:
|
| 7 |
+
|
| 8 |
+
``` bnf
|
| 9 |
+
constraint-expression:
|
| 10 |
+
logical-or-expression
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
Constraints can also be associated with a declaration through the use of
|
| 14 |
+
*type-constraint*s in a *template-parameter-list* or
|
| 15 |
+
parameter-type-list. Each of these forms introduces additional
|
| 16 |
+
*constraint-expression*s that are used to constrain the declaration.
|
| 17 |
+
|
| 18 |
+
A declaration’s *associated constraints* are defined as follows:
|
| 19 |
+
|
| 20 |
+
- If there are no introduced *constraint-expression*s, the declaration
|
| 21 |
+
has no associated constraints.
|
| 22 |
+
- Otherwise, if there is a single introduced *constraint-expression*,
|
| 23 |
+
the associated constraints are the normal form [[temp.constr.normal]]
|
| 24 |
+
of that expression.
|
| 25 |
+
- Otherwise, the associated constraints are the normal form of a logical
|
| 26 |
+
expression [[expr.log.and]] whose operands are in the following order:
|
| 27 |
+
- the *constraint-expression* introduced by each *type-constraint*
|
| 28 |
+
[[temp.param]] in the declaration’s *template-parameter-list*, in
|
| 29 |
+
order of appearance, and
|
| 30 |
+
- the *constraint-expression* introduced by a *requires-clause*
|
| 31 |
+
following a *template-parameter-list* [[temp.pre]], and
|
| 32 |
+
- the *constraint-expression* introduced by each *type-constraint* in
|
| 33 |
+
the parameter-type-list of a function declaration, and
|
| 34 |
+
- the *constraint-expression* introduced by a trailing
|
| 35 |
+
*requires-clause* [[dcl.decl]] of a function declaration
|
| 36 |
+
[[dcl.fct]].
|
| 37 |
+
|
| 38 |
+
The formation of the associated constraints establishes the order in
|
| 39 |
+
which constraints are instantiated when checking for satisfaction
|
| 40 |
+
[[temp.constr.constr]].
|
| 41 |
+
|
| 42 |
+
[*Example 1*:
|
| 43 |
+
|
| 44 |
+
``` cpp
|
| 45 |
+
template<typename T> concept C = true;
|
| 46 |
+
|
| 47 |
+
template<C T> void f1(T);
|
| 48 |
+
template<typename T> requires C<T> void f2(T);
|
| 49 |
+
template<typename T> void f3(T) requires C<T>;
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
The functions `f1`, `f2`, and `f3` have the associated constraint
|
| 53 |
+
`C<T>`.
|
| 54 |
+
|
| 55 |
+
``` cpp
|
| 56 |
+
template<typename T> concept C1 = true;
|
| 57 |
+
template<typename T> concept C2 = sizeof(T) > 0;
|
| 58 |
+
|
| 59 |
+
template<C1 T> void f4(T) requires C2<T>;
|
| 60 |
+
template<typename T> requires C1<T> && C2<T> void f5(T);
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
The associated constraints of `f4` and `f5` are `C1<T> ∧ C2<T>`.
|
| 64 |
+
|
| 65 |
+
``` cpp
|
| 66 |
+
template<C1 T> requires C2<T> void f6();
|
| 67 |
+
template<C2 T> requires C1<T> void f7();
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
The associated constraints of `f6` are `C1<T> ∧ C2<T>`, and those of
|
| 71 |
+
`f7` are `C2<T> ∧ C1<T>`.
|
| 72 |
+
|
| 73 |
+
— *end example*]
|
| 74 |
+
|
| 75 |
+
When determining whether a given introduced *constraint-expression* C₁
|
| 76 |
+
of a declaration in an instantiated specialization of a templated class
|
| 77 |
+
is equivalent [[temp.over.link]] to the corresponding
|
| 78 |
+
*constraint-expression* C₂ of a declaration outside the class body, C₁
|
| 79 |
+
is instantiated. If the instantiation results in an invalid expression,
|
| 80 |
+
the *constraint-expression*s are not equivalent.
|
| 81 |
+
|
| 82 |
+
[*Note 1*: This can happen when determining which member template is
|
| 83 |
+
specialized by an explicit specialization declaration. — *end note*]
|
| 84 |
+
|
| 85 |
+
[*Example 2*:
|
| 86 |
+
|
| 87 |
+
``` cpp
|
| 88 |
+
template <class T> concept C = true;
|
| 89 |
+
template <class T> struct A {
|
| 90 |
+
template <class U> U f(U) requires C<typename T::type>; // #1
|
| 91 |
+
template <class U> U f(U) requires C<T>; // #2
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
template <> template <class U>
|
| 95 |
+
U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
Substituting `int` for `T` in `C<typename T::type>` produces an invalid
|
| 99 |
+
expression, so the specialization does not match \#1. Substituting `int`
|
| 100 |
+
for `T` in `C<T>` produces `C<int>`, which is equivalent to the
|
| 101 |
+
*constraint-expression* for the specialization, so it does match \#2.
|
| 102 |
+
|
| 103 |
+
— *end example*]
|
| 104 |
+
|