C++ 为什么';t显式bool()转换发生在上下文转换中

C++ 为什么';t显式bool()转换发生在上下文转换中,c++,c++11,operator-overloading,C++,C++11,Operator Overloading,如果以下测试程序 #include <iostream> class A { public: A() {} explicit operator bool() const { std::cout << __PRETTY_FUNCTION__ << std::endl; return true; } // explicit operator bool() { // std::cout &

如果以下测试程序

#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;
    }
}
而不是

bool A::operator _Bool()
bool()
int A::operator int()
int()
我所期望的(以及如果取消注释已注释的部分会得到什么)

所以问题是,什么规则赋予转换为非常量int的优先级高于转换为常量bool的优先级

什么规则使转换为非常量int优先于转换为常量bool

使用非常量对象的常量成员函数,需要将非常量对象转换为常量对象。这就是为什么
运算符int()
运算符bool()const
更匹配的原因

更清楚地说,如果要删除int运算符,第一个bool上下文(first if)的实际情况如下:

if ( const_cast<const A&>(a).operator bool() ) {
if ( a.operator int() )

在对引用绑定执行重载解析时,首选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()
}
请注意,将对象绑定到成员函数的隐式对象参数(13.3.1.1.1p2)是一种参考绑定(13.3.3.1.4)

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

重要的是,只有在考虑转换运算符自身之间的过载解决方案后,才考虑转换运算符返回类型所需的任何转换(13.3.3p1)


解决方案是确保所有转换运算符都具有相同的
const
-限定条件,特别是对于标量类型。

哪个编译器
const operator int()const
如果编译失败,编译器将发出clang-3.4是否可以更新问题标题以删除双负号。我会自己做,但我不确定是删除“不”还是“不”。或者两者都有?好吧,只是澄清了标题。谢谢由于OPs问题中的注释运算符也是显式的,并且仅仅因为
const
而改变了行为,所以这个答案实际上不起作用。此外,显式
运算符bool
可以在布尔上下文中使用,而无需强制转换(例如
if
)。这是在C++11中实现安全bool习惯用法的一种非常简单的方法。因此,要正确使用C++11中的expilicit bool习惯用法,必须同时实现运算符bool()的常量和非常量版本。只是为了防止其他转换操作符介入?我不太明白这个重载解析的排名是如何发生的。通常,将一些
A
绑定到
A常量&
是直接引用绑定,因此被认为是完全匹配的。因此,在这两种情况下,隐式对象参数都应该与隐式对象参数完全匹配。然后,两者都有一个UDC,但是对于到
int
的转换,后面是布尔转换。显然,编译器中并没有发生这种情况,隐含对象参数的匹配在某种程度上排名不同。@wimalopaan要么如此,要么只实现const版本的转换运算符。@dyp我试图找出标准中哪一段是重要的。我认为它是[conv.quel],但它谈论的是指针,而不是引用。它仍然需要从左值转换为prvalue来调用
运算符bool()const
,从而使
运算符int()
更合格。“重要的是,只有在考虑转换运算符本身之间的重载解析后,才考虑转换运算符返回类型所需的任何转换(13.3.3p1)。”嗯,有一个以“上下文是通过用户定义的转换进行初始化”开头的项目符号,它似乎暗示这是完全有意的+1@dyp这里没有UDCS,因为我们没有使用
X
参数在不同的函数之间解析。如果我们有
f(bool),就会有UDCSs;f(浮动);X;f(x)和确实那些UDCS是不明确的。从
A
bool
的整个转换是一个UDCS(在OP的例子中),但重载解决方案应用“太早”IMHO,其中不考虑从
A
bool
所需的UDC,而仅用于定义可行的函数(因此,重载解析只考虑隐含对象参数的SCS)。嗯,您的示例可能就是转换函数重载解析发生得如此之早的原因:如果上下文是对重载函数的调用(而不像OP中,是具有固定目标类型的转换),有两个重载解析步骤要执行:1.选择转换函数2.选择
f
的重载。
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()
}