没有operator ==()的类的对象将转换为另一种类型

Ale*_*sky 8 c++ c++17

为什么在以下代码中将类A的对象转换为bool(或int):

class A
{
public:

    operator bool() const { return true; }
    operator int() const { return 1; }
};

int main()
{
    return A() == A();
}
Run Code Online (Sandbox Code Playgroud)

目前还不清楚他们转变成了什么?bool或int?

Bar*_*rry 6

我们需要找到如何处理==.这将涉及寻找成员,非成员和内置候选人==.在这种情况下,我们没有任何成员/非成员候选人,因此这部分很容易.

内置候选人来自[over.built]/13(强调我的,并删节):

对于每对提升的算术类型 LR,存在该形式的候选运算符函数

bool operator==(L, R);

促进算术类型是升级后的整型和浮点类型.任何整体型小于int(包括bool)促进int.(float 促进double,但float仍然是一个"提升算术类型").对我们来说,这一点的重要部分实际上是"推广的算术类型"包括int但不包括bool.如此有效,我们有内置的候选人,如:

bool operator==(int, int);
bool operator==(int, long);
bool operator==(long, int);
bool operator==(long, long);
bool operator==(int, float);
// etc.
Run Code Online (Sandbox Code Playgroud)

这一组中有很多候选人.但我们基本上可以将它们分成两组.

第一组完全由以下部分组成:

bool operator==(int, int);
Run Code Online (Sandbox Code Playgroud)

这个候选人是可行的,我们有一个明确的最佳转换顺序,因为通过operator int() const比通过operator bool() const然后推广更好.

第二组由其他所有候选人组成.对于没有的每个提升的算术类型int,我们有两个等价的转换序列:一个通过bool转换,一个通过int转换.两者都不比另一个好.当我第一次写这个答案时,我认为这意味着这些候选人会被拒绝 - 但令人惊讶的是,正如TC所指出的那样:一个模糊的转换序列被等同于任何其他用户定义的转换序列.

因此,从第一组开始,我们有一个可行的候选者,其涉及用户定义的转换序列.从第二组开始,我们有很多具有模糊转换序列的候选者 - 这对于operator==(int, int)第一组中的候选人来说同样重要.

结果,A() == A()是不正确的.没有最好的可行候选人.gcc接受这个是错误的.


请注意,gcc确实拒绝了同样想法的非常类似的其他演示:

void check(int, int);
void check(float, float);

check(A(), A()); // gcc and clang reject, msvc accepts
Run Code Online (Sandbox Code Playgroud)