From Jason Turner

[temp.constr.op]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpwt3stmeq/{from.md → to.md} +87 -0
tmp/tmpwt3stmeq/{from.md → to.md} RENAMED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Logical operations <a id="temp.constr.op">[[temp.constr.op]]</a>
2
+
3
+ There are two binary logical operations on constraints: conjunction and
4
+ disjunction.
5
+
6
+ [*Note 1*: These logical operations have no corresponding C++ syntax.
7
+ For the purpose of exposition, conjunction is spelled using the symbol ∧
8
+ and disjunction is spelled using the symbol ∨. The operands of these
9
+ operations are called the left and right operands. In the constraint
10
+ A ∧ B, A is the left operand, and B is the right operand. — *end note*]
11
+
12
+ A *conjunction* is a constraint taking two operands. To determine if a
13
+ conjunction is *satisfied*, the satisfaction of the first operand is
14
+ checked. If that is not satisfied, the conjunction is not satisfied.
15
+ Otherwise, the conjunction is satisfied if and only if the second
16
+ operand is satisfied.
17
+
18
+ A *disjunction* is a constraint taking two operands. To determine if a
19
+ disjunction is *satisfied*, the satisfaction of the first operand is
20
+ checked. If that is satisfied, the disjunction is satisfied. Otherwise,
21
+ the disjunction is satisfied if and only if the second operand is
22
+ satisfied.
23
+
24
+ [*Example 1*:
25
+
26
+ ``` cpp
27
+ template<typename T>
28
+ constexpr bool get_value() { return T::value; }
29
+
30
+ template<typename T>
31
+ requires (sizeof(T) > 1) && (get_value<T>())
32
+ void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value<T>()
33
+
34
+ void f(int);
35
+
36
+ f('a'); // OK: calls f(int)
37
+ ```
38
+
39
+ In the satisfaction of the associated constraints [[temp.constr.decl]]
40
+ of `f`, the constraint `sizeof(char) > 1` is not satisfied; the second
41
+ operand is not checked for satisfaction.
42
+
43
+ — *end example*]
44
+
45
+ [*Note 2*:
46
+
47
+ A logical negation expression [[expr.unary.op]] is an atomic constraint;
48
+ the negation operator is not treated as a logical operation on
49
+ constraints. As a result, distinct negation *constraint-expression*s
50
+ that are equivalent under  [[temp.over.link]] do not subsume one another
51
+ under  [[temp.constr.order]]. Furthermore, if substitution to determine
52
+ whether an atomic constraint is satisfied [[temp.constr.atomic]]
53
+ encounters a substitution failure, the constraint is not satisfied,
54
+ regardless of the presence of a negation operator.
55
+
56
+ [*Example 2*:
57
+
58
+ ``` cpp
59
+ template <class T> concept sad = false;
60
+
61
+ template <class T> int f1(T) requires (!sad<T>);
62
+ template <class T> int f1(T) requires (!sad<T>) && true;
63
+ int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions[temp.constr.atomic]
64
+ // are not formed from the same expression
65
+
66
+ template <class T> concept not_sad = !sad<T>;
67
+ template <class T> int f2(T) requires not_sad<T>;
68
+ template <class T> int f2(T) requires not_sad<T> && true;
69
+ int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sad
70
+
71
+ template <class T> int f3(T) requires (!sad<typename T::type>);
72
+ int i3 = f3(42); // error: associated constraints not satisfied due to substitution failure
73
+
74
+ template <class T> concept sad_nested_type = sad<typename T::type>;
75
+ template <class T> int f4(T) requires (!sad_nested_type<T>);
76
+ int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
77
+ ```
78
+
79
+ Here, `requires (!sad<typename T::type>)` requires that there is a
80
+ nested `type` that is not `sad`, whereas
81
+ `requires (!sad_nested_type<T>)` requires that there is no `sad` nested
82
+ `type`.
83
+
84
+ — *end example*]
85
+
86
+ — *end note*]
87
+