From Jason Turner

[temp.constr.normal]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp1g9e6r_6/{from.md → to.md} +105 -6
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
- - The normal form of a concept-id `C<A₁, A₂, ..., Aₙ>` is the normal
12
- form of the *constraint-expression* of `C`, after substituting
13
- `A₁, A₂, ..., Aₙ` for `C`'s respective template parameters in the
14
- parameter mappings in each atomic constraint. If any such substitution
15
- results in an invalid type or expression, the program is ill-formed;
16
- no diagnostic is required.
 
 
 
 
 
 
 
 
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
+