From Jason Turner

[temp.constr]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp6sw71c94/{from.md → to.md} +463 -0
tmp/tmp6sw71c94/{from.md → to.md} RENAMED
@@ -0,0 +1,463 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Template constraints <a id="temp.constr">[[temp.constr]]</a>
2
+
3
+ [*Note 1*: This subclause defines the meaning of constraints on
4
+ template arguments. The abstract syntax and satisfaction rules are
5
+ defined in [[temp.constr.constr]]. Constraints are associated with
6
+ declarations in [[temp.constr.decl]]. Declarations are partially ordered
7
+ by their associated constraints [[temp.constr.order]]. — *end note*]
8
+
9
+ ### Constraints <a id="temp.constr.constr">[[temp.constr.constr]]</a>
10
+
11
+ A *constraint* is a sequence of logical operations and operands that
12
+ specifies requirements on template arguments. The operands of a logical
13
+ operation are constraints. There are three different kinds of
14
+ constraints:
15
+
16
+ - conjunctions [[temp.constr.op]],
17
+ - disjunctions [[temp.constr.op]], and
18
+ - atomic constraints [[temp.constr.atomic]].
19
+
20
+ In order for a constrained template to be instantiated [[temp.spec]],
21
+ its associated constraints [[temp.constr.decl]] shall be satisfied as
22
+ described in the following subclauses.
23
+
24
+ [*Note 1*: Forming the name of a specialization of a class template, a
25
+ variable template, or an alias template [[temp.names]] requires the
26
+ satisfaction of its constraints. Overload resolution
27
+ [[over.match.viable]] requires the satisfaction of constraints on
28
+ functions and function templates. — *end note*]
29
+
30
+ #### Logical operations <a id="temp.constr.op">[[temp.constr.op]]</a>
31
+
32
+ There are two binary logical operations on constraints: conjunction and
33
+ disjunction.
34
+
35
+ [*Note 1*: These logical operations have no corresponding C++ syntax.
36
+ For the purpose of exposition, conjunction is spelled using the symbol ∧
37
+ and disjunction is spelled using the symbol ∨. The operands of these
38
+ operations are called the left and right operands. In the constraint
39
+ A ∧ B, A is the left operand, and B is the right operand. — *end note*]
40
+
41
+ A *conjunction* is a constraint taking two operands. To determine if a
42
+ conjunction is *satisfied*, the satisfaction of the first operand is
43
+ checked. If that is not satisfied, the conjunction is not satisfied.
44
+ Otherwise, the conjunction is satisfied if and only if the second
45
+ operand is satisfied.
46
+
47
+ A *disjunction* is a constraint taking two operands. To determine if a
48
+ disjunction is *satisfied*, the satisfaction of the first operand is
49
+ checked. If that is satisfied, the disjunction is satisfied. Otherwise,
50
+ the disjunction is satisfied if and only if the second operand is
51
+ satisfied.
52
+
53
+ [*Example 1*:
54
+
55
+ ``` cpp
56
+ template<typename T>
57
+ constexpr bool get_value() { return T::value; }
58
+
59
+ template<typename T>
60
+ requires (sizeof(T) > 1) && (get_value<T>())
61
+ void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value<T>()
62
+
63
+ void f(int);
64
+
65
+ f('a'); // OK: calls f(int)
66
+ ```
67
+
68
+ In the satisfaction of the associated constraints [[temp.constr.decl]]
69
+ of `f`, the constraint `sizeof(char) > 1` is not satisfied; the second
70
+ operand is not checked for satisfaction.
71
+
72
+ — *end example*]
73
+
74
+ [*Note 2*:
75
+
76
+ A logical negation expression [[expr.unary.op]] is an atomic constraint;
77
+ the negation operator is not treated as a logical operation on
78
+ constraints. As a result, distinct negation *constraint-expression*s
79
+ that are equivalent under  [[temp.over.link]] do not subsume one another
80
+ under  [[temp.constr.order]]. Furthermore, if substitution to determine
81
+ whether an atomic constraint is satisfied [[temp.constr.atomic]]
82
+ encounters a substitution failure, the constraint is not satisfied,
83
+ regardless of the presence of a negation operator.
84
+
85
+ [*Example 2*:
86
+
87
+ ``` cpp
88
+ template <class T> concept sad = false;
89
+
90
+ template <class T> int f1(T) requires (!sad<T>);
91
+ template <class T> int f1(T) requires (!sad<T>) && true;
92
+ int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions[temp.constr.atomic]
93
+ // are not formed from the same expression
94
+
95
+ template <class T> concept not_sad = !sad<T>;
96
+ template <class T> int f2(T) requires not_sad<T>;
97
+ template <class T> int f2(T) requires not_sad<T> && true;
98
+ int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sad
99
+
100
+ template <class T> int f3(T) requires (!sad<typename T::type>);
101
+ int i3 = f3(42); // error: associated constraints not satisfied due to substitution failure
102
+
103
+ template <class T> concept sad_nested_type = sad<typename T::type>;
104
+ template <class T> int f4(T) requires (!sad_nested_type<T>);
105
+ int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
106
+ ```
107
+
108
+ Here, `requires (!sad<typename T::type>)` requires that there is a
109
+ nested `type` that is not `sad`, whereas
110
+ `requires (!sad_nested_type<T>)` requires that there is no `sad` nested
111
+ `type`.
112
+
113
+ — *end example*]
114
+
115
+ — *end note*]
116
+
117
+ #### Atomic constraints <a id="temp.constr.atomic">[[temp.constr.atomic]]</a>
118
+
119
+ An *atomic constraint* is formed from an expression `E` and a mapping
120
+ from the template parameters that appear within `E` to template
121
+ arguments that are formed via substitution during constraint
122
+ normalization in the declaration of a constrained entity (and,
123
+ therefore, can involve the unsubstituted template parameters of the
124
+ constrained entity), called the *parameter mapping*
125
+ [[temp.constr.decl]].
126
+
127
+ [*Note 1*: Atomic constraints are formed by constraint normalization
128
+ [[temp.constr.normal]]. `E` is never a logical expression
129
+ [[expr.log.and]] nor a logical expression
130
+ [[expr.log.or]]. — *end note*]
131
+
132
+ Two atomic constraints, e₁ and e₂, are *identical* if they are formed
133
+ from the same appearance of the same *expression* and if, given a
134
+ hypothetical template A whose *template-parameter-list* consists of
135
+ *template-parameter*s corresponding and equivalent [[temp.over.link]] to
136
+ those mapped by the parameter mappings of the expression, a
137
+ *template-id* naming A whose *template-argument*s are the targets of the
138
+ parameter mapping of e₁ is the same [[temp.type]] as a *template-id*
139
+ naming A whose *template-argument*s are the targets of the parameter
140
+ mapping of e₂.
141
+
142
+ [*Note 2*:
143
+
144
+ The comparison of parameter mappings of atomic constraints operates in a
145
+ manner similar to that of declaration matching with alias template
146
+ substitution [[temp.alias]].
147
+
148
+ [*Example 1*:
149
+
150
+ ``` cpp
151
+ template <unsigned N> constexpr bool Atomic = true;
152
+ template <unsigned N> concept C = Atomic<N>;
153
+ template <unsigned N> concept Add1 = C<N + 1>;
154
+ template <unsigned N> concept AddOne = C<N + 1>;
155
+ template <unsigned M> void f()
156
+ requires Add1<2 * M>;
157
+ template <unsigned M> int f()
158
+ requires AddOne<2 * M> && true;
159
+
160
+ int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>
161
+ // with mapping similar to `N` ↦ `2 * M + 1`
162
+
163
+ template <unsigned N> struct WrapN;
164
+ template <unsigned N> using Add1Ty = WrapN<N + 1>;
165
+ template <unsigned N> using AddOneTy = WrapN<N + 1>;
166
+ template <unsigned M> void g(Add1Ty<2 * M> *);
167
+ template <unsigned M> void g(AddOneTy<2 * M> *);
168
+
169
+ void h() {
170
+ g<0>(nullptr); // OK, there is only one g
171
+ }
172
+ ```
173
+
174
+ — *end example*]
175
+
176
+ This similarity includes the situation where a program is ill-formed, no
177
+ diagnostic required, when the meaning of the program depends on whether
178
+ two constructs are equivalent, and they are functionally equivalent but
179
+ not equivalent.
180
+
181
+ [*Example 2*:
182
+
183
+ ``` cpp
184
+ template <unsigned N> void f2()
185
+ requires Add1<2 * N>;
186
+ template <unsigned N> int f2()
187
+ requires Add1<N * 2> && true;
188
+ void h2() {
189
+ f2<0>(); // ill-formed, no diagnostic required:
190
+ // requires determination of subsumption between atomic constraints that are
191
+ // functionally equivalent but not equivalent
192
+ }
193
+ ```
194
+
195
+ — *end example*]
196
+
197
+ — *end note*]
198
+
199
+ To determine if an atomic constraint is *satisfied*, the parameter
200
+ mapping and template arguments are first substituted into its
201
+ expression. If substitution results in an invalid type or expression,
202
+ the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
203
+ conversion [[conv.lval]] is performed if necessary, and `E` shall be a
204
+ constant expression of type `bool`. The constraint is satisfied if and
205
+ only if evaluation of `E` results in `true`. If, at different points in
206
+ the program, the satisfaction result is different for identical atomic
207
+ constraints and template arguments, the program is ill-formed, no
208
+ diagnostic required.
209
+
210
+ [*Example 3*:
211
+
212
+ ``` cpp
213
+ template<typename T> concept C =
214
+ sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !true
215
+
216
+ template<typename T> struct S {
217
+ constexpr operator bool() const { return true; }
218
+ };
219
+
220
+ template<typename T> requires (S<T>{})
221
+ void f(T); // #1
222
+ void f(int); // #2
223
+
224
+ void g() {
225
+ f(0); // error: expression S<int>{} does not have type bool
226
+ } // while checking satisfaction of deduced arguments of #1;
227
+ // call is ill-formed even though #2 is a better match
228
+ ```
229
+
230
+ — *end example*]
231
+
232
+ ### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
233
+
234
+ A template declaration [[temp.pre]] or templated function declaration
235
+ [[dcl.fct]] can be constrained by the use of a *requires-clause*. This
236
+ allows the specification of constraints for that declaration as an
237
+ expression:
238
+
239
+ ``` bnf
240
+ constraint-expression:
241
+ logical-or-expression
242
+ ```
243
+
244
+ Constraints can also be associated with a declaration through the use of
245
+ *type-constraint*s in a *template-parameter-list* or
246
+ parameter-type-list. Each of these forms introduces additional
247
+ *constraint-expression*s that are used to constrain the declaration.
248
+
249
+ A declaration’s *associated constraints* are defined as follows:
250
+
251
+ - If there are no introduced *constraint-expression*s, the declaration
252
+ has no associated constraints.
253
+ - Otherwise, if there is a single introduced *constraint-expression*,
254
+ the associated constraints are the normal form [[temp.constr.normal]]
255
+ of that expression.
256
+ - Otherwise, the associated constraints are the normal form of a logical
257
+ expression [[expr.log.and]] whose operands are in the following order:
258
+ - the *constraint-expression* introduced by each *type-constraint*
259
+ [[temp.param]] in the declaration’s *template-parameter-list*, in
260
+ order of appearance, and
261
+ - the *constraint-expression* introduced by a *requires-clause*
262
+ following a *template-parameter-list* [[temp.pre]], and
263
+ - the *constraint-expression* introduced by each *type-constraint* in
264
+ the parameter-type-list of a function declaration, and
265
+ - the *constraint-expression* introduced by a trailing
266
+ *requires-clause* [[dcl.decl]] of a function declaration
267
+ [[dcl.fct]].
268
+
269
+ The formation of the associated constraints establishes the order in
270
+ which constraints are instantiated when checking for satisfaction
271
+ [[temp.constr.constr]].
272
+
273
+ [*Example 1*:
274
+
275
+ ``` cpp
276
+ template<typename T> concept C = true;
277
+
278
+ template<C T> void f1(T);
279
+ template<typename T> requires C<T> void f2(T);
280
+ template<typename T> void f3(T) requires C<T>;
281
+ ```
282
+
283
+ The functions `f1`, `f2`, and `f3` have the associated constraint
284
+ `C<T>`.
285
+
286
+ ``` cpp
287
+ template<typename T> concept C1 = true;
288
+ template<typename T> concept C2 = sizeof(T) > 0;
289
+
290
+ template<C1 T> void f4(T) requires C2<T>;
291
+ template<typename T> requires C1<T> && C2<T> void f5(T);
292
+ ```
293
+
294
+ The associated constraints of `f4` and `f5` are `C1<T> ∧ C2<T>`.
295
+
296
+ ``` cpp
297
+ template<C1 T> requires C2<T> void f6();
298
+ template<C2 T> requires C1<T> void f7();
299
+ ```
300
+
301
+ The associated constraints of `f6` are `C1<T> ∧ C2<T>`, and those of
302
+ `f7` are `C2<T> ∧ C1<T>`.
303
+
304
+ — *end example*]
305
+
306
+ When determining whether a given introduced *constraint-expression* C₁
307
+ of a declaration in an instantiated specialization of a templated class
308
+ is equivalent [[temp.over.link]] to the corresponding
309
+ *constraint-expression* C₂ of a declaration outside the class body, C₁
310
+ is instantiated. If the instantiation results in an invalid expression,
311
+ the *constraint-expression*s are not equivalent.
312
+
313
+ [*Note 1*: This can happen when determining which member template is
314
+ specialized by an explicit specialization declaration. — *end note*]
315
+
316
+ [*Example 2*:
317
+
318
+ ``` cpp
319
+ template <class T> concept C = true;
320
+ template <class T> struct A {
321
+ template <class U> U f(U) requires C<typename T::type>; // #1
322
+ template <class U> U f(U) requires C<T>; // #2
323
+ };
324
+
325
+ template <> template <class U>
326
+ U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
327
+ ```
328
+
329
+ Substituting `int` for `T` in `C<typename T::type>` produces an invalid
330
+ expression, so the specialization does not match \#1. Substituting `int`
331
+ for `T` in `C<T>` produces `C<int>`, which is equivalent to the
332
+ *constraint-expression* for the specialization, so it does match \#2.
333
+
334
+ — *end example*]
335
+
336
+ ### Constraint normalization <a id="temp.constr.normal">[[temp.constr.normal]]</a>
337
+
338
+ The *normal form* of an *expression* `E` is a constraint
339
+ [[temp.constr.constr]] that is defined as follows:
340
+
341
+ - The normal form of an expression `( E )` is the normal form of `E`.
342
+ - The normal form of an expression `E1 || E2` is the disjunction
343
+ [[temp.constr.op]] of the normal forms of `E1` and `E2`.
344
+ - The normal form of an expression `E1 && E2` is the conjunction of the
345
+ normal forms of `E1` and `E2`.
346
+ - The normal form of a concept-id `C<A₁, A₂, ..., Aₙ>` is the normal
347
+ form of the *constraint-expression* of `C`, after substituting
348
+ `A₁, A₂, ..., Aₙ` for `C`'s respective template parameters in the
349
+ parameter mappings in each atomic constraint. If any such substitution
350
+ results in an invalid type or expression, the program is ill-formed;
351
+ no diagnostic is required.
352
+ \[*Example 1*:
353
+ ``` cpp
354
+ template<typename T> concept A = T::value || true;
355
+ template<typename U> concept B = A<U*>;
356
+ template<typename V> concept C = B<V&>;
357
+ ```
358
+
359
+ Normalization of `B`'s *constraint-expression* is valid and results in
360
+ `T::value` (with the mapping `T` ↦ `U*`) ∨ `true` (with an empty
361
+ mapping), despite the expression `T::value` being ill-formed for a
362
+ pointer type `T`. Normalization of `C`'s *constraint-expression*
363
+ results in the program being ill-formed, because it would form the
364
+ invalid type `V&*` in the parameter mapping.
365
+ — *end example*]
366
+ - The normal form of any other expression `E` is the atomic constraint
367
+ whose expression is `E` and whose parameter mapping is the identity
368
+ mapping.
369
+
370
+ The process of obtaining the normal form of a *constraint-expression* is
371
+ called *normalization*.
372
+
373
+ [*Note 1*: Normalization of *constraint-expression*s is performed when
374
+ determining the associated constraints [[temp.constr.constr]] of a
375
+ declaration and when evaluating the value of an *id-expression* that
376
+ names a concept specialization [[expr.prim.id]]. — *end note*]
377
+
378
+ [*Example 2*:
379
+
380
+ ``` cpp
381
+ template<typename T> concept C1 = sizeof(T) == 1;
382
+ template<typename T> concept C2 = C1<T> && 1 == 2;
383
+ template<typename T> concept C3 = requires { typename T::type; };
384
+ template<typename T> concept C4 = requires (T x) { ++x; }
385
+
386
+ template<C2 U> void f1(U); // #1
387
+ template<C3 U> void f2(U); // #2
388
+ template<C4 U> void f3(U); // #3
389
+ ```
390
+
391
+ The associated constraints of \#1 are `sizeof(T) == 1` (with mapping
392
+ `T` ↦ `U`) ∧ `1 == 2`.
393
+ The associated constraints of \#2 are `requires { typename T::type; }`
394
+ (with mapping `T` ↦ `U`).
395
+ The associated constraints of \#3 are `requires (T x) { ++x; }` (with
396
+ mapping `T` ↦ `U`).
397
+
398
+ — *end example*]
399
+
400
+ ### Partial ordering by constraints <a id="temp.constr.order">[[temp.constr.order]]</a>
401
+
402
+ A constraint P *subsumes* a constraint Q if and only if, for every
403
+ disjunctive clause Pᵢ in the disjunctive normal form[^4] of P, Pᵢ
404
+ subsumes every conjunctive clause Qⱼ in the conjunctive normal form[^5]
405
+ of Q, where
406
+
407
+ - a disjunctive clause Pᵢ subsumes a conjunctive clause Qⱼ if and only
408
+ if there exists an atomic constraint Pᵢₐ in Pᵢ for which there exists
409
+ an atomic constraint $Q_{jb}$ in Qⱼ such that Pᵢₐ subsumes $Q_{jb}$,
410
+ and
411
+ - an atomic constraint A subsumes another atomic constraint B if and
412
+ only if A and B are identical using the rules described in
413
+ [[temp.constr.atomic]].
414
+
415
+ [*Example 1*: Let A and B be atomic constraints [[temp.constr.atomic]].
416
+ The constraint A ∧ B subsumes A, but A does not subsume A ∧ B. The
417
+ constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note
418
+ that every constraint subsumes itself. — *end example*]
419
+
420
+ [*Note 1*:
421
+
422
+ The subsumption relation defines a partial ordering on constraints. This
423
+ partial ordering is used to determine
424
+
425
+ - the best viable candidate of non-template functions
426
+ [[over.match.best]],
427
+ - the address of a non-template function [[over.over]],
428
+ - the matching of template template arguments [[temp.arg.template]],
429
+ - the partial ordering of class template specializations
430
+ [[temp.class.order]], and
431
+ - the partial ordering of function templates [[temp.func.order]].
432
+
433
+ — *end note*]
434
+
435
+ A declaration `D1` is *at least as constrained* as a declaration `D2` if
436
+
437
+ - `D1` and `D2` are both constrained declarations and `D1`’s associated
438
+ constraints subsume those of `D2`; or
439
+ - `D2` has no associated constraints.
440
+
441
+ A declaration `D1` is *more constrained* than another declaration `D2`
442
+ when `D1` is at least as constrained as `D2`, and `D2` is not at least
443
+ as constrained as `D1`.
444
+
445
+ [*Example 2*:
446
+
447
+ ``` cpp
448
+ template<typename T> concept C1 = requires(T t) { --t; };
449
+ template<typename T> concept C2 = C1<T> && requires(T t) { *t; };
450
+
451
+ template<C1 T> void f(T); // #1
452
+ template<C2 T> void f(T); // #2
453
+ template<typename T> void g(T); // #3
454
+ template<C1 T> void g(T); // #4
455
+
456
+ f(0); // selects #1
457
+ f((int*)0); // selects #2
458
+ g(true); // selects #3 because C1<bool> is not satisfied
459
+ g(0); // selects #4
460
+ ```
461
+
462
+ — *end example*]
463
+