[expr.unary.op]/9 似乎暗示 `operator !()` 不能应用于下面的类型 A。但编译器不同意这一点
[expr.unary.op]/9 seems to imply that the `operator !()` could not be applied to the type A below. But compilers disagree with that
Certain language constructs require that an expression be converted to
a Boolean value. An expression e
appearing in such a context is said
to be contextually converted to bool
and is well-formed if and
only if the declaration bool t(e);
is well-formed, for some invented
temporary variable t
(11.6).
现在考虑下面的片段。它不编译,也不在 clang, GCC or VS.
struct A{ bool operator!() { return true; } };
int main(){
A a;
bool t(a);
}
因此,从 [conv]/4 我们得出结论,类型 A
是 而不是 上下文转换为 bool
.
The operand of the logical negation operator !
is contextually
converted to bool
(Clause 7); its value is true
if the converted
operand is false
and false
otherwise. The type of the result is
bool
.
我对上面这段的理解是,逻辑非运算符!
的操作数必须根据上下文转换为bool
。我们刚刚得出结论,类型 A
是 而不是 上下文转换为 bool
。因此,从[expr.unary.op]/9,我们可以说下面的代码应该不编译。但确实如此,在 clang, GCC and VS.
struct A{ bool operator!() { return true; } };
int main(){
A a;
bool t = !a;
}
我错过了什么?
[expr]整体适用于内置运算符:
Clause [expr] defines the effects of operators when applied to types for which they have not been overloaded.
[expr.unary.op]中的定义只是内置operator!
的定义。此外,[over.match.oper] 描述了如何查找重载运算符:
For a unary operator @ with an operand of a type whose cv-unqualified version is T1, [...], three sets of candidate functions, designated member candidates, non-member candidates and built-in candidates, are constructed as follows: [...]
对于 !a
,您有两个候选对象:您的重载 A::operator!()
和 [over.built] 中定义的内置:
There also exist candidate operator functions of the form
bool operator!(bool);
对于通过重载决议选择的内置函数,类型必须根据上下文转换为 bool
† 正如您的论点所建议的那样。然而,这个候选者是不可行的——但是重载的成员运算符是可行的。
† is on top of it as usual, pointing out cwg issue 1919 这表明 是 上下文可转换为 bool
的类型仍然不应该由于措辞问题,请使用内置 operator!
。尽管 gcc 和 clang 都允许它(这可能是我们都希望发生的事情)。
Certain language constructs require that an expression be converted to a Boolean value. An expression
e
appearing in such a context is said to be contextually converted tobool
and is well-formed if and only if the declarationbool t(e);
is well-formed, for some invented temporary variablet
(11.6).
现在考虑下面的片段。它不编译,也不在 clang, GCC or VS.
struct A{ bool operator!() { return true; } };
int main(){
A a;
bool t(a);
}
因此,从 [conv]/4 我们得出结论,类型 A
是 而不是 上下文转换为 bool
.
The operand of the logical negation operator
!
is contextually converted tobool
(Clause 7); its value istrue
if the converted operand isfalse
andfalse
otherwise. The type of the result isbool
.
我对上面这段的理解是,逻辑非运算符!
的操作数必须根据上下文转换为bool
。我们刚刚得出结论,类型 A
是 而不是 上下文转换为 bool
。因此,从[expr.unary.op]/9,我们可以说下面的代码应该不编译。但确实如此,在 clang, GCC and VS.
struct A{ bool operator!() { return true; } };
int main(){
A a;
bool t = !a;
}
我错过了什么?
[expr]整体适用于内置运算符:
Clause [expr] defines the effects of operators when applied to types for which they have not been overloaded.
[expr.unary.op]中的定义只是内置operator!
的定义。此外,[over.match.oper] 描述了如何查找重载运算符:
For a unary operator @ with an operand of a type whose cv-unqualified version is T1, [...], three sets of candidate functions, designated member candidates, non-member candidates and built-in candidates, are constructed as follows: [...]
对于 !a
,您有两个候选对象:您的重载 A::operator!()
和 [over.built] 中定义的内置:
There also exist candidate operator functions of the form
bool operator!(bool);
对于通过重载决议选择的内置函数,类型必须根据上下文转换为 bool
† 正如您的论点所建议的那样。然而,这个候选者是不可行的——但是重载的成员运算符是可行的。
†bool
的类型仍然不应该由于措辞问题,请使用内置 operator!
。尽管 gcc 和 clang 都允许它(这可能是我们都希望发生的事情)。