From Jason Turner

[temp.constr]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpl7njrojk/{from.md → to.md} +234 -15
tmp/tmpl7njrojk/{from.md → to.md} RENAMED
@@ -12,16 +12,18 @@ by their associated constraints [[temp.constr.order]]. — *end note*]
12
 
13
  #### General <a id="temp.constr.constr.general">[[temp.constr.constr.general]]</a>
14
 
15
  A *constraint* is a sequence of logical operations and operands that
16
  specifies requirements on template arguments. The operands of a logical
17
- operation are constraints. There are three different kinds of
18
  constraints:
19
 
20
  - conjunctions [[temp.constr.op]],
21
- - disjunctions [[temp.constr.op]], and
22
- - atomic constraints [[temp.constr.atomic]].
 
 
23
 
24
  In order for a constrained template to be instantiated [[temp.spec]],
25
  its associated constraints [[temp.constr.decl]] shall be satisfied as
26
  described in the following subclauses.
27
 
@@ -200,11 +202,12 @@ void h2() {
200
 
201
  — *end note*]
202
 
203
  To determine if an atomic constraint is *satisfied*, the parameter
204
  mapping and template arguments are first substituted into its
205
- expression. If substitution results in an invalid type or expression,
 
206
  the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
207
  conversion [[conv.lval]] is performed if necessary, and `E` shall be a
208
  constant expression of type `bool`. The constraint is satisfied if and
209
  only if evaluation of `E` results in `true`. If, at different points in
210
  the program, the satisfaction result is different for identical atomic
@@ -231,10 +234,93 @@ void g() {
231
  // call is ill-formed even though #2 is a better match
232
  ```
233
 
234
  — *end example*]
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  ### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
237
 
238
  A template declaration [[temp.pre]] or templated function declaration
239
  [[dcl.fct]] can be constrained by the use of a *requires-clause*. This
240
  allows the specification of constraints for that declaration as an
@@ -345,16 +431,24 @@ The *normal form* of an *expression* `E` is a constraint
345
  - The normal form of an expression `( E )` is the normal form of `E`.
346
  - The normal form of an expression `E1 || E2` is the disjunction
347
  [[temp.constr.op]] of the normal forms of `E1` and `E2`.
348
  - The normal form of an expression `E1 && E2` is the conjunction of the
349
  normal forms of `E1` and `E2`.
350
- - The normal form of a concept-id `C<A₁, A₂, ..., Aₙ>` is the normal
351
- form of the *constraint-expression* of `C`, after substituting
352
- `A₁, A₂, ..., Aₙ` for `C`'s respective template parameters in the
353
- parameter mappings in each atomic constraint. If any such substitution
354
- results in an invalid type or expression, the program is ill-formed;
355
- no diagnostic is required.
 
 
 
 
 
 
 
 
356
  \[*Example 1*:
357
  ``` cpp
358
  template<typename T> concept A = T::value || true;
359
  template<typename U> concept B = A<U*>;
360
  template<typename V> concept C = B<V&>;
@@ -365,10 +459,35 @@ The *normal form* of an *expression* `E` is a constraint
365
  mapping), despite the expression `T::value` being ill-formed for a
366
  pointer type `T`. Normalization of `C`'s *constraint-expression*
367
  results in the program being ill-formed, because it would form the
368
  invalid type `V&*` in the parameter mapping.
369
  — *end example*]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  - The normal form of any other expression `E` is the atomic constraint
371
  whose expression is `E` and whose parameter mapping is the identity
372
  mapping.
373
 
374
  The process of obtaining the normal form of a *constraint-expression* is
@@ -399,27 +518,95 @@ The associated constraints of \#2 are `requires { typename T::type; }`
399
  The associated constraints of \#3 are `requires (T x) { ++x; }` (with
400
  mapping `T` ↦ `U`).
401
 
402
  — *end example*]
403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  ### Partial ordering by constraints <a id="temp.constr.order">[[temp.constr.order]]</a>
405
 
406
  A constraint P *subsumes* a constraint Q if and only if, for every
407
- disjunctive clause Pᵢ in the disjunctive normal form[^4]
408
 
409
  of P, Pᵢ subsumes every conjunctive clause Qⱼ in the conjunctive normal
410
- form[^5]
411
 
412
  of Q, where
413
 
414
  - a disjunctive clause Pᵢ subsumes a conjunctive clause Qⱼ if and only
415
  if there exists an atomic constraint Pᵢₐ in Pᵢ for which there exists
416
  an atomic constraint $Q_{jb}$ in Qⱼ such that Pᵢₐ subsumes $Q_{jb}$,
417
- and
418
  - an atomic constraint A subsumes another atomic constraint B if and
419
  only if A and B are identical using the rules described in
420
- [[temp.constr.atomic]].
 
 
 
421
 
422
  [*Example 1*: Let A and B be atomic constraints [[temp.constr.atomic]].
423
  The constraint A ∧ B subsumes A, but A does not subsume A ∧ B. The
424
  constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note
425
  that every constraint subsumes itself. — *end example*]
@@ -437,14 +624,17 @@ partial ordering is used to determine
437
  [[temp.spec.partial.order]], and
438
  - the partial ordering of function templates [[temp.func.order]].
439
 
440
  — *end note*]
441
 
 
 
 
442
  A declaration `D1` is *at least as constrained* as a declaration `D2` if
443
 
444
  - `D1` and `D2` are both constrained declarations and `D1`’s associated
445
- constraints subsume those of `D2`; or
446
  - `D2` has no associated constraints.
447
 
448
  A declaration `D1` is *more constrained* than another declaration `D2`
449
  when `D1` is at least as constrained as `D2`, and `D2` is not at least
450
  as constrained as `D1`.
@@ -466,5 +656,34 @@ g(true); // selects #3 because C1<bool> is not satisfied
466
  g(0); // selects #4
467
  ```
468
 
469
  — *end example*]
470
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  #### General <a id="temp.constr.constr.general">[[temp.constr.constr.general]]</a>
14
 
15
  A *constraint* is a sequence of logical operations and operands that
16
  specifies requirements on template arguments. The operands of a logical
17
+ operation are constraints. There are five different kinds of
18
  constraints:
19
 
20
  - conjunctions [[temp.constr.op]],
21
+ - disjunctions [[temp.constr.op]],
22
+ - atomic constraints [[temp.constr.atomic]],
23
+ - concept-dependent constraints [[temp.constr.concept]], and
24
+ - fold expanded constraints [[temp.constr.fold]].
25
 
26
  In order for a constrained template to be instantiated [[temp.spec]],
27
  its associated constraints [[temp.constr.decl]] shall be satisfied as
28
  described in the following subclauses.
29
 
 
202
 
203
  — *end note*]
204
 
205
  To determine if an atomic constraint is *satisfied*, the parameter
206
  mapping and template arguments are first substituted into its
207
+ expression. If substitution results in an invalid type or expression in
208
+ the immediate context of the atomic constraint [[temp.deduct.general]],
209
  the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
210
  conversion [[conv.lval]] is performed if necessary, and `E` shall be a
211
  constant expression of type `bool`. The constraint is satisfied if and
212
  only if evaluation of `E` results in `true`. If, at different points in
213
  the program, the satisfaction result is different for identical atomic
 
234
  // call is ill-formed even though #2 is a better match
235
  ```
236
 
237
  — *end example*]
238
 
239
+ #### Concept-dependent constraints <a id="temp.constr.concept">[[temp.constr.concept]]</a>
240
+
241
+ A *concept-dependent constraint* `CD` is an atomic constraint whose
242
+ expression is a concept-id `CI` whose *concept-name* names a dependent
243
+ concept named `C`.
244
+
245
+ To determine if `CD` is *satisfied*, the parameter mapping and template
246
+ arguments are first substituted into `C`. If substitution results in an
247
+ invalid concept-id in the immediate context of the constraint
248
+ [[temp.deduct.general]], the constraint is not satisfied. Otherwise, let
249
+ `CI'` be the normal form [[temp.constr.normal]] of the concept-id after
250
+ substitution of `C`.
251
+
252
+ [*Note 1*: Normalization of `CI` might be ill-formed; no diagnostic is
253
+ required. — *end note*]
254
+
255
+ To form `CI''`, each appearance of `C`'s template parameters in the
256
+ parameter mappings of the atomic constraints (including
257
+ concept-dependent constraints) in `CI'` is substituted with their
258
+ respective arguments from the parameter mapping of `CD` and the
259
+ arguments of `CI`.
260
+
261
+ `CD` is satisfied if `CI''` is satisfied.
262
+
263
+ [*Note 2*: Checking whether `CI''` is satisfied can lead to further
264
+ normalization of concept-dependent constraints. — *end note*]
265
+
266
+ [*Example 1*:
267
+
268
+ ``` cpp
269
+ template<typename>
270
+ concept C = true;
271
+
272
+ template<typename T, template<typename> concept CC>
273
+ concept D = CC<T>;
274
+
275
+ template<typename U,
276
+ template<typename> concept CT,
277
+ template<typename, template<typename> concept> concept CU>
278
+ int f() requires CU<U, CT>;
279
+ int i = f<int, C, D>();
280
+ ```
281
+
282
+ In this example, the associated constraints of `f` consist of a
283
+ concept-dependent constraint whose expression is the concept-id
284
+ `CU<U, CT>` with the mapping `U` ↦ `U`, `CT` ↦ `CT`, `CU` ↦ `CU`. The
285
+ result of substituting `D` into this expression is `D<U, CT>`. We
286
+ consider the normal form of the resulting concept-id, which is `CC<T>`
287
+ with the mapping `T` ↦ `U`, `CC` ↦ `CT`. By recursion, `C` is
288
+ substituted into `CC<T>`, and the result is normalized to the atomic
289
+ constraint `true`, which is satisfied.
290
+
291
+ — *end example*]
292
+
293
+ #### Fold expanded constraint <a id="temp.constr.fold">[[temp.constr.fold]]</a>
294
+
295
+ A *fold expanded constraint* is formed from a constraint C and a
296
+ *fold-operator* which can either be `&&` or `||`. A fold expanded
297
+ constraint is a pack expansion [[temp.variadic]]. Let N be the number of
298
+ elements in the pack expansion parameters [[temp.variadic]].
299
+
300
+ A fold expanded constraint whose *fold-operator* is `&&` is satisfied if
301
+ it is a valid pack expansion and if N = 0 or if for each i where
302
+ 0 ≤ i < N in increasing order, C is satisfied when replacing each pack
303
+ expansion parameter with the corresponding iᵗʰ element. No substitution
304
+ takes place for any i greater than the smallest i for which the
305
+ constraint is not satisfied.
306
+
307
+ A fold expanded constraint whose *fold-operator* is `||` is satisfied if
308
+ it is a valid pack expansion, N > 0, and if for i where 0 ≤ i < N in
309
+ increasing order, there is a smallest i for which C is satisfied when
310
+ replacing each pack expansion parameter with the corresponding iᵗʰ
311
+ element. No substitution takes place for any i greater than the smallest
312
+ i for which the constraint is satisfied.
313
+
314
+ [*Note 1*: If the pack expansion expands packs of different size, then
315
+ it is invalid and the fold expanded constraint is not
316
+ satisfied. — *end note*]
317
+
318
+ Two fold expanded constraints are *compatible for subsumption* if their
319
+ respective constraints both contain an equivalent unexpanded pack
320
+ [[temp.over.link]].
321
+
322
  ### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
323
 
324
  A template declaration [[temp.pre]] or templated function declaration
325
  [[dcl.fct]] can be constrained by the use of a *requires-clause*. This
326
  allows the specification of constraints for that declaration as an
 
431
  - The normal form of an expression `( E )` is the normal form of `E`.
432
  - The normal form of an expression `E1 || E2` is the disjunction
433
  [[temp.constr.op]] of the normal forms of `E1` and `E2`.
434
  - The normal form of an expression `E1 && E2` is the conjunction of the
435
  normal forms of `E1` and `E2`.
436
+ - For a concept-id `C<A₁, A₂, , Aₙ>` termed `CI`:
437
+ - If `C` names a dependent concept, the normal form of `CI` is a
438
+ concept-dependent constraint whose concept-id is `CI` and whose
439
+ parameter mapping is the identity mapping.
440
+ - Otherwise, to form `CE`, any non-dependent concept template argument
441
+ `Aᵢ` is substituted into the *constraint-expression* of `C`. If any
442
+ such substitution results in an invalid concept-id, the program is
443
+ ill-formed; no diagnostic is required. The normal form of `CI` is
444
+ the result of substituting, in the normal form `N` of `CE`,
445
+ appearances of `C`'s template parameters in the parameter mappings
446
+ of the atomic constraints in `N` with their respective arguments
447
+ from `C`. If any such substitution results in an invalid type or
448
+ expression, the program is ill-formed; no diagnostic is required.
449
+
450
  \[*Example 1*:
451
  ``` cpp
452
  template<typename T> concept A = T::value || true;
453
  template<typename U> concept B = A<U*>;
454
  template<typename V> concept C = B<V&>;
 
459
  mapping), despite the expression `T::value` being ill-formed for a
460
  pointer type `T`. Normalization of `C`'s *constraint-expression*
461
  results in the program being ill-formed, because it would form the
462
  invalid type `V&*` in the parameter mapping.
463
  — *end example*]
464
+ - For a *fold-operator* `Op` [[expr.prim.fold]] that is either `&&` or
465
+ `||`:
466
+ - The normal form of an expression `( ... Op E )` is the normal form
467
+ of `( E Op ... )`.
468
+ - The normal form of an expression `( E1 Op ... Op E2 )` is the normal
469
+ form of
470
+ - `( E1 Op ... ) Op E2` if `E1` contains an unexpanded pack, or
471
+ - `E1 Op ( E2 Op ... )` otherwise.
472
+ - The normal form of an expression `F` of the form `( E Op ... )` is
473
+ as follows:
474
+ If `E` contains an unexpanded concept template parameter pack, it
475
+ shall not contain an unexpanded template parameter pack of another
476
+ kind. Let `E'` be the normal form of `E`.
477
+ - If `E` contains an unexpanded concept template parameter pack `Pₖ`
478
+ that has corresponding template arguments in the parameter mapping
479
+ of any atomic constraint (including concept-dependent constraints)
480
+ of `E'`, the number of arguments specified for all such `Pₖ` shall
481
+ be the same number N. The normal form of `F` is the normal form of
482
+ `E₀ Op … Op E_{N-1}` after substituting in `Eᵢ` the respective iᵗʰ
483
+ concept argument of each `Pₖ`. If any such substitution results in
484
+ an invalid type or expression, the program is ill-formed; no
485
+ diagnostic is required.
486
+ - Otherwise, the normal form of `F` is a fold expanded constraint
487
+ [[temp.constr.fold]] whose constraint is `E'` and whose
488
+ *fold-operator* is `Op`.
489
  - The normal form of any other expression `E` is the atomic constraint
490
  whose expression is `E` and whose parameter mapping is the identity
491
  mapping.
492
 
493
  The process of obtaining the normal form of a *constraint-expression* is
 
518
  The associated constraints of \#3 are `requires (T x) { ++x; }` (with
519
  mapping `T` ↦ `U`).
520
 
521
  — *end example*]
522
 
523
+ [*Example 3*:
524
+
525
+ ``` cpp
526
+ template<typename T>
527
+ concept C = true;
528
+ template<typename T, template<typename> concept CT>
529
+ concept CC = CT<T>;
530
+
531
+ template<typename U,
532
+ template<typename, template<typename> concept> concept CT>
533
+ void f() requires CT<U*, C>;
534
+ template<typename U>
535
+ void g() requires CC<U*, C>;
536
+ ```
537
+
538
+ The normal form of the associated constraints of `f` is the
539
+ concept-dependent constraint `CT<T, C>`.
540
+ The normal form of the associated constraints of `g` is the atomic
541
+ constraint `true`.
542
+
543
+ — *end example*]
544
+
545
+ [*Example 4*:
546
+
547
+ ``` cpp
548
+ template<typename T>
549
+ concept A = true;
550
+ template<typename T>
551
+ concept B = A<T> && true; // B subsumes A
552
+ template<typename T>
553
+ concept C = true;
554
+ template<typename T>
555
+ concept D = C<T> && true; // D subsumes C
556
+
557
+ template<typename T, template<typename> concept... CTs>
558
+ concept all_of = (CTs<T> && ...);
559
+
560
+ template<typename T> requires all_of<T, A, C>
561
+ constexpr int f(T) { return 1; } // #1
562
+ template<typename T> requires all_of<T, B, D>
563
+ constexpr int f(T) { return 2; } // #2
564
+
565
+ static_assert(f(1) == 2); // ok
566
+ ```
567
+
568
+ The normal form of `all_of<T, A, C>` is the conjunction of the normal
569
+ forms of `A<T>` and `C<T>`.
570
+ Similarly, the normal form of `all_of<T, B, D>` is the conjunction of
571
+ the normal forms of `B<T>` and `D<T>`.
572
+ \#2 therefore is more constrained than \#1.
573
+
574
+ — *end example*]
575
+
576
+ [*Example 5*:
577
+
578
+ ``` cpp
579
+ template<typename T, template<typename> concept>
580
+ struct wrapper {};
581
+
582
+ template<typename... T, template<typename> concept... CTs>
583
+ int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains
584
+ // different kinds of template parameters
585
+ ```
586
+
587
+ — *end example*]
588
+
589
  ### Partial ordering by constraints <a id="temp.constr.order">[[temp.constr.order]]</a>
590
 
591
  A constraint P *subsumes* a constraint Q if and only if, for every
592
+ disjunctive clause Pᵢ in the disjunctive normal form[^3]
593
 
594
  of P, Pᵢ subsumes every conjunctive clause Qⱼ in the conjunctive normal
595
+ form[^4]
596
 
597
  of Q, where
598
 
599
  - a disjunctive clause Pᵢ subsumes a conjunctive clause Qⱼ if and only
600
  if there exists an atomic constraint Pᵢₐ in Pᵢ for which there exists
601
  an atomic constraint $Q_{jb}$ in Qⱼ such that Pᵢₐ subsumes $Q_{jb}$,
 
602
  - an atomic constraint A subsumes another atomic constraint B if and
603
  only if A and B are identical using the rules described in
604
+ [[temp.constr.atomic]], and
605
+ - a fold expanded constraint A subsumes another fold expanded constraint
606
+ B if they are compatible for subsumption, have the same
607
+ *fold-operator*, and the constraint of A subsumes that of B.
608
 
609
  [*Example 1*: Let A and B be atomic constraints [[temp.constr.atomic]].
610
  The constraint A ∧ B subsumes A, but A does not subsume A ∧ B. The
611
  constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note
612
  that every constraint subsumes itself. — *end example*]
 
624
  [[temp.spec.partial.order]], and
625
  - the partial ordering of function templates [[temp.func.order]].
626
 
627
  — *end note*]
628
 
629
+ The associated constraints `C` of a declaration `D` are *eligible for
630
+ subsumption* unless `C` contains a concept-dependent constraint.
631
+
632
  A declaration `D1` is *at least as constrained* as a declaration `D2` if
633
 
634
  - `D1` and `D2` are both constrained declarations and `D1`’s associated
635
+ constraints are eligible for subsumption and subsume those of `D2`; or
636
  - `D2` has no associated constraints.
637
 
638
  A declaration `D1` is *more constrained* than another declaration `D2`
639
  when `D1` is at least as constrained as `D2`, and `D2` is not at least
640
  as constrained as `D1`.
 
656
  g(0); // selects #4
657
  ```
658
 
659
  — *end example*]
660
 
661
+ [*Example 3*:
662
+
663
+ ``` cpp
664
+ template<template<typename T> concept CT, typename T>
665
+ struct S {};
666
+ template<typename T>
667
+ concept A = true;
668
+
669
+ template<template<typename T> concept X, typename T>
670
+ int f(S<X, T>) requires A<T> { return 42; } // #1
671
+ template<template<typename T> concept X, typename T>
672
+ int f(S<X, T>) requires X<T> { return 43; } // #2
673
+
674
+ f(S<A, int>{}); // ok, select #1 because #2 is not eligible for subsumption
675
+ ```
676
+
677
+ — *end example*]
678
+
679
+ A non-template function `F1` is *more partial-ordering-constrained* than
680
+ a non-template function `F2` if
681
+
682
+ - they have the same non-object-parameter-type-lists [[dcl.fct]], and
683
+ - if they are member functions, both are direct members of the same
684
+ class, and
685
+ - if both are non-static member functions, they have the same types for
686
+ their object parameters, and
687
+ - the declaration of `F1` is more constrained than the declaration of
688
+ `F2`.
689
+