5.1 KiB
[temp.constr.op]
13 Templates [temp]
13.5 Template constraints [temp.constr]
13.5.2 Constraints [temp.constr.constr]
13.5.2.2 Logical operations [temp.constr.op]
There are two binary logical operations on constraints: conjunction and disjunction.
[Note 1:
These logical operations have no corresponding C++ syntax.
For the purpose of exposition, conjunction is spelled using the symbol ⧠and disjunction is spelled using the symbol ⨠.
The operands of these operations are called the left and right operands.
In the constraint A â§ B,A is the left operand, and B is the right operand.
â end note]
A conjunction is a constraint taking two operands.
To determine if a conjunction issatisfied, the satisfaction of the first operand is checked.
If that is not satisfied, the conjunction is not satisfied.
Otherwise, the conjunction is satisfied if and only if the second operand is satisfied.
A disjunction is a constraint taking two operands.
To determine if a disjunction issatisfied, the satisfaction of the first operand is checked.
If that is satisfied, the disjunction is satisfied.
Otherwise, the disjunction is satisfied if and only if the second operand is satisfied.
[Example 1: templateconstexpr bool get_value() { return T::value; }templaterequires (sizeof(T) > 1) && (get_value())void f(T); // has associated constraint sizeof(T) > 1 â§ get_value()void f(int);
f('a'); // OK, calls f(int)
In the satisfaction of the associated constraints of f, the constraint sizeof(char) > 1 is not satisfied; the second operand is not checked for satisfaction.
â end example]
[Note 2:
A logical negation expression ([expr.unary.op]) is an atomic constraint; the negation operator is not treated as a logical operation on constraints.
As a result, distinct negation constraint-expressions that are equivalent under [temp.over.link] do not subsume one another under [temp.constr.order].
Furthermore, if substitution to determine whether an atomic constraint is satisfied ([temp.constr.atomic]) encounters a substitution failure, the constraint is not satisfied, regardless of the presence of a negation operator.
[Example 2: template concept sad = false;
template int f1(T) requires (!sad);template int f1(T) requires (!sad) && true;int i1 = f1(42); // ambiguous, !sad atomic constraint expressions ([temp.constr.atomic])// are not formed from the same expressiontemplate concept not_sad = !sad;template int f2(T) requires not_sad;template int f2(T) requires not_sad && true;int i2 = f2(42); // OK, !sad atomic constraint expressions both come from not_sadtemplate int f3(T) requires (!sad);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate concept sad_nested_type = sad;template int f4(T) requires (!sad_nested_type);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
Here,requires (!sad<typename T::type>) requires that there is a nested type that is not sad, whereasrequires (!sad_nested_type) requires that there is no sad nested type.
â end example]
â end note]