tmp/tmp1g9e6r_6/{from.md → to.md}
RENAMED
|
@@ -6,16 +6,24 @@ The *normal form* of an *expression* `E` is a constraint
|
|
| 6 |
- The normal form of an expression `( E )` is the normal form of `E`.
|
| 7 |
- The normal form of an expression `E1 || E2` is the disjunction
|
| 8 |
[[temp.constr.op]] of the normal forms of `E1` and `E2`.
|
| 9 |
- The normal form of an expression `E1 && E2` is the conjunction of the
|
| 10 |
normal forms of `E1` and `E2`.
|
| 11 |
-
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
\[*Example 1*:
|
| 18 |
``` cpp
|
| 19 |
template<typename T> concept A = T::value || true;
|
| 20 |
template<typename U> concept B = A<U*>;
|
| 21 |
template<typename V> concept C = B<V&>;
|
|
@@ -26,10 +34,35 @@ The *normal form* of an *expression* `E` is a constraint
|
|
| 26 |
mapping), despite the expression `T::value` being ill-formed for a
|
| 27 |
pointer type `T`. Normalization of `C`'s *constraint-expression*
|
| 28 |
results in the program being ill-formed, because it would form the
|
| 29 |
invalid type `V&*` in the parameter mapping.
|
| 30 |
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
- The normal form of any other expression `E` is the atomic constraint
|
| 32 |
whose expression is `E` and whose parameter mapping is the identity
|
| 33 |
mapping.
|
| 34 |
|
| 35 |
The process of obtaining the normal form of a *constraint-expression* is
|
|
@@ -60,5 +93,71 @@ The associated constraints of \#2 are `requires { typename T::type; }`
|
|
| 60 |
The associated constraints of \#3 are `requires (T x) { ++x; }` (with
|
| 61 |
mapping `T` ↦ `U`).
|
| 62 |
|
| 63 |
— *end example*]
|
| 64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
- The normal form of an expression `( E )` is the normal form of `E`.
|
| 7 |
- The normal form of an expression `E1 || E2` is the disjunction
|
| 8 |
[[temp.constr.op]] of the normal forms of `E1` and `E2`.
|
| 9 |
- The normal form of an expression `E1 && E2` is the conjunction of the
|
| 10 |
normal forms of `E1` and `E2`.
|
| 11 |
+
- For a concept-id `C<A₁, A₂, …, Aₙ>` termed `CI`:
|
| 12 |
+
- If `C` names a dependent concept, the normal form of `CI` is a
|
| 13 |
+
concept-dependent constraint whose concept-id is `CI` and whose
|
| 14 |
+
parameter mapping is the identity mapping.
|
| 15 |
+
- Otherwise, to form `CE`, any non-dependent concept template argument
|
| 16 |
+
`Aᵢ` is substituted into the *constraint-expression* of `C`. If any
|
| 17 |
+
such substitution results in an invalid concept-id, the program is
|
| 18 |
+
ill-formed; no diagnostic is required. The normal form of `CI` is
|
| 19 |
+
the result of substituting, in the normal form `N` of `CE`,
|
| 20 |
+
appearances of `C`'s template parameters in the parameter mappings
|
| 21 |
+
of the atomic constraints in `N` with their respective arguments
|
| 22 |
+
from `C`. If any such substitution results in an invalid type or
|
| 23 |
+
expression, the program is ill-formed; no diagnostic is required.
|
| 24 |
+
|
| 25 |
\[*Example 1*:
|
| 26 |
``` cpp
|
| 27 |
template<typename T> concept A = T::value || true;
|
| 28 |
template<typename U> concept B = A<U*>;
|
| 29 |
template<typename V> concept C = B<V&>;
|
|
|
|
| 34 |
mapping), despite the expression `T::value` being ill-formed for a
|
| 35 |
pointer type `T`. Normalization of `C`'s *constraint-expression*
|
| 36 |
results in the program being ill-formed, because it would form the
|
| 37 |
invalid type `V&*` in the parameter mapping.
|
| 38 |
— *end example*]
|
| 39 |
+
- For a *fold-operator* `Op` [[expr.prim.fold]] that is either `&&` or
|
| 40 |
+
`||`:
|
| 41 |
+
- The normal form of an expression `( ... Op E )` is the normal form
|
| 42 |
+
of `( E Op ... )`.
|
| 43 |
+
- The normal form of an expression `( E1 Op ... Op E2 )` is the normal
|
| 44 |
+
form of
|
| 45 |
+
- `( E1 Op ... ) Op E2` if `E1` contains an unexpanded pack, or
|
| 46 |
+
- `E1 Op ( E2 Op ... )` otherwise.
|
| 47 |
+
- The normal form of an expression `F` of the form `( E Op ... )` is
|
| 48 |
+
as follows:
|
| 49 |
+
If `E` contains an unexpanded concept template parameter pack, it
|
| 50 |
+
shall not contain an unexpanded template parameter pack of another
|
| 51 |
+
kind. Let `E'` be the normal form of `E`.
|
| 52 |
+
- If `E` contains an unexpanded concept template parameter pack `Pₖ`
|
| 53 |
+
that has corresponding template arguments in the parameter mapping
|
| 54 |
+
of any atomic constraint (including concept-dependent constraints)
|
| 55 |
+
of `E'`, the number of arguments specified for all such `Pₖ` shall
|
| 56 |
+
be the same number N. The normal form of `F` is the normal form of
|
| 57 |
+
`E₀ Op … Op E_{N-1}` after substituting in `Eᵢ` the respective iᵗʰ
|
| 58 |
+
concept argument of each `Pₖ`. If any such substitution results in
|
| 59 |
+
an invalid type or expression, the program is ill-formed; no
|
| 60 |
+
diagnostic is required.
|
| 61 |
+
- Otherwise, the normal form of `F` is a fold expanded constraint
|
| 62 |
+
[[temp.constr.fold]] whose constraint is `E'` and whose
|
| 63 |
+
*fold-operator* is `Op`.
|
| 64 |
- The normal form of any other expression `E` is the atomic constraint
|
| 65 |
whose expression is `E` and whose parameter mapping is the identity
|
| 66 |
mapping.
|
| 67 |
|
| 68 |
The process of obtaining the normal form of a *constraint-expression* is
|
|
|
|
| 93 |
The associated constraints of \#3 are `requires (T x) { ++x; }` (with
|
| 94 |
mapping `T` ↦ `U`).
|
| 95 |
|
| 96 |
— *end example*]
|
| 97 |
|
| 98 |
+
[*Example 3*:
|
| 99 |
+
|
| 100 |
+
``` cpp
|
| 101 |
+
template<typename T>
|
| 102 |
+
concept C = true;
|
| 103 |
+
template<typename T, template<typename> concept CT>
|
| 104 |
+
concept CC = CT<T>;
|
| 105 |
+
|
| 106 |
+
template<typename U,
|
| 107 |
+
template<typename, template<typename> concept> concept CT>
|
| 108 |
+
void f() requires CT<U*, C>;
|
| 109 |
+
template<typename U>
|
| 110 |
+
void g() requires CC<U*, C>;
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
The normal form of the associated constraints of `f` is the
|
| 114 |
+
concept-dependent constraint `CT<T, C>`.
|
| 115 |
+
The normal form of the associated constraints of `g` is the atomic
|
| 116 |
+
constraint `true`.
|
| 117 |
+
|
| 118 |
+
— *end example*]
|
| 119 |
+
|
| 120 |
+
[*Example 4*:
|
| 121 |
+
|
| 122 |
+
``` cpp
|
| 123 |
+
template<typename T>
|
| 124 |
+
concept A = true;
|
| 125 |
+
template<typename T>
|
| 126 |
+
concept B = A<T> && true; // B subsumes A
|
| 127 |
+
template<typename T>
|
| 128 |
+
concept C = true;
|
| 129 |
+
template<typename T>
|
| 130 |
+
concept D = C<T> && true; // D subsumes C
|
| 131 |
+
|
| 132 |
+
template<typename T, template<typename> concept... CTs>
|
| 133 |
+
concept all_of = (CTs<T> && ...);
|
| 134 |
+
|
| 135 |
+
template<typename T> requires all_of<T, A, C>
|
| 136 |
+
constexpr int f(T) { return 1; } // #1
|
| 137 |
+
template<typename T> requires all_of<T, B, D>
|
| 138 |
+
constexpr int f(T) { return 2; } // #2
|
| 139 |
+
|
| 140 |
+
static_assert(f(1) == 2); // ok
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
The normal form of `all_of<T, A, C>` is the conjunction of the normal
|
| 144 |
+
forms of `A<T>` and `C<T>`.
|
| 145 |
+
Similarly, the normal form of `all_of<T, B, D>` is the conjunction of
|
| 146 |
+
the normal forms of `B<T>` and `D<T>`.
|
| 147 |
+
\#2 therefore is more constrained than \#1.
|
| 148 |
+
|
| 149 |
+
— *end example*]
|
| 150 |
+
|
| 151 |
+
[*Example 5*:
|
| 152 |
+
|
| 153 |
+
``` cpp
|
| 154 |
+
template<typename T, template<typename> concept>
|
| 155 |
+
struct wrapper {};
|
| 156 |
+
|
| 157 |
+
template<typename... T, template<typename> concept... CTs>
|
| 158 |
+
int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains
|
| 159 |
+
// different kinds of template parameters
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
— *end example*]
|
| 163 |
+
|