From Jason Turner

[temp.constr.atomic]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp7i1_m67j/{from.md → to.md} +115 -0
tmp/tmp7i1_m67j/{from.md → to.md} RENAMED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Atomic constraints <a id="temp.constr.atomic">[[temp.constr.atomic]]</a>
2
+
3
+ An *atomic constraint* is formed from an expression `E` and a mapping
4
+ from the template parameters that appear within `E` to template
5
+ arguments that are formed via substitution during constraint
6
+ normalization in the declaration of a constrained entity (and,
7
+ therefore, can involve the unsubstituted template parameters of the
8
+ constrained entity), called the *parameter mapping*
9
+ [[temp.constr.decl]].
10
+
11
+ [*Note 1*: Atomic constraints are formed by constraint normalization
12
+ [[temp.constr.normal]]. `E` is never a logical expression
13
+ [[expr.log.and]] nor a logical expression
14
+ [[expr.log.or]]. — *end note*]
15
+
16
+ Two atomic constraints, e₁ and e₂, are *identical* if they are formed
17
+ from the same appearance of the same *expression* and if, given a
18
+ hypothetical template A whose *template-parameter-list* consists of
19
+ *template-parameter*s corresponding and equivalent [[temp.over.link]] to
20
+ those mapped by the parameter mappings of the expression, a
21
+ *template-id* naming A whose *template-argument*s are the targets of the
22
+ parameter mapping of e₁ is the same [[temp.type]] as a *template-id*
23
+ naming A whose *template-argument*s are the targets of the parameter
24
+ mapping of e₂.
25
+
26
+ [*Note 2*:
27
+
28
+ The comparison of parameter mappings of atomic constraints operates in a
29
+ manner similar to that of declaration matching with alias template
30
+ substitution [[temp.alias]].
31
+
32
+ [*Example 1*:
33
+
34
+ ``` cpp
35
+ template <unsigned N> constexpr bool Atomic = true;
36
+ template <unsigned N> concept C = Atomic<N>;
37
+ template <unsigned N> concept Add1 = C<N + 1>;
38
+ template <unsigned N> concept AddOne = C<N + 1>;
39
+ template <unsigned M> void f()
40
+ requires Add1<2 * M>;
41
+ template <unsigned M> int f()
42
+ requires AddOne<2 * M> && true;
43
+
44
+ int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>
45
+ // with mapping similar to `N` ↦ `2 * M + 1`
46
+
47
+ template <unsigned N> struct WrapN;
48
+ template <unsigned N> using Add1Ty = WrapN<N + 1>;
49
+ template <unsigned N> using AddOneTy = WrapN<N + 1>;
50
+ template <unsigned M> void g(Add1Ty<2 * M> *);
51
+ template <unsigned M> void g(AddOneTy<2 * M> *);
52
+
53
+ void h() {
54
+ g<0>(nullptr); // OK, there is only one g
55
+ }
56
+ ```
57
+
58
+ — *end example*]
59
+
60
+ This similarity includes the situation where a program is ill-formed, no
61
+ diagnostic required, when the meaning of the program depends on whether
62
+ two constructs are equivalent, and they are functionally equivalent but
63
+ not equivalent.
64
+
65
+ [*Example 2*:
66
+
67
+ ``` cpp
68
+ template <unsigned N> void f2()
69
+ requires Add1<2 * N>;
70
+ template <unsigned N> int f2()
71
+ requires Add1<N * 2> && true;
72
+ void h2() {
73
+ f2<0>(); // ill-formed, no diagnostic required:
74
+ // requires determination of subsumption between atomic constraints that are
75
+ // functionally equivalent but not equivalent
76
+ }
77
+ ```
78
+
79
+ — *end example*]
80
+
81
+ — *end note*]
82
+
83
+ To determine if an atomic constraint is *satisfied*, the parameter
84
+ mapping and template arguments are first substituted into its
85
+ expression. If substitution results in an invalid type or expression,
86
+ the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
87
+ conversion [[conv.lval]] is performed if necessary, and `E` shall be a
88
+ constant expression of type `bool`. The constraint is satisfied if and
89
+ only if evaluation of `E` results in `true`. If, at different points in
90
+ the program, the satisfaction result is different for identical atomic
91
+ constraints and template arguments, the program is ill-formed, no
92
+ diagnostic required.
93
+
94
+ [*Example 3*:
95
+
96
+ ``` cpp
97
+ template<typename T> concept C =
98
+ sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !true
99
+
100
+ template<typename T> struct S {
101
+ constexpr operator bool() const { return true; }
102
+ };
103
+
104
+ template<typename T> requires (S<T>{})
105
+ void f(T); // #1
106
+ void f(int); // #2
107
+
108
+ void g() {
109
+ f(0); // error: expression S<int>{} does not have type bool
110
+ } // while checking satisfaction of deduced arguments of #1;
111
+ // call is ill-formed even though #2 is a better match
112
+ ```
113
+
114
+ — *end example*]
115
+