为什么在上下文转换中没有发生显式的bool()转换

wim*_*aan 16 c++ operator-overloading c++11

如果以下测试程序

#include <iostream>

class A {
public:
    A() {}
    explicit operator bool() const {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        return true;
    }
//    explicit operator bool() {
//        std::cout << __PRETTY_FUNCTION__ << std::endl;
//        return true;
//    }
    const operator int() const {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        return 1;
    }
    operator int() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        return 1;
    }
};

int main() {
    A a;
    if (a) {
        std::cout << "bool()" << std::endl;
    }
    if (a + 0) {
        std::cout << "int()" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

运行,输出是

int A::operator int()
bool()
int A::operator int()
int()
Run Code Online (Sandbox Code Playgroud)

并不是

bool A::operator _Bool()
bool()
int A::operator int()
int()
Run Code Online (Sandbox Code Playgroud)

我所期望的(以及如果你取消注释评论部分你会得到什么).

所以问题是什么是转换为非const-int优先级而不是转换为const-bool的规则?

eca*_*mur 10

在引用绑定上执行重载解析时,首选的是较少cv限定的类型.这将在13.3.3.2p3中讨论,给出的示例如下:

struct X {
  void f() const;
  void f();
};
void g(const X& a, X b) {
  a.f(); // calls X::f() const
  b.f(); // calls X::f()
}
Run Code Online (Sandbox Code Playgroud)

请注意,将对象绑定到成员函数(13.3.1.1.1p2)的隐式对象参数是引用绑定(13.3.3.1.4).

转换运算符被视为成员函数(13.3.1.5),用于重载解析(13.3p2).上下文转换bool具有初始化的语义(4p4).

重要的是,只有考虑转换运算符本身之间的重载分辨率(13.3.3p1)之后,才会考虑转换运算符的返回类型所需的任何转换.

解决方案是确保所有转换运算符具有相同的const限定条件,尤其是标量类型.