2014-02-27 18 views
14

如果下面的測試PROGRAMM爲什麼不明確的布爾()轉換的上下文轉換髮生

#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; 
    } 
} 

運行時,輸出爲

int A::operator int() 
bool() 
int A::operator int() 
int() 

,而不是

bool A::operator _Bool() 
bool() 
int A::operator int() 
int() 

我所期望的(以及如果取消評論部分的評論,你會得到什麼)。

所以問題是什麼規則將轉換爲非const-int優先轉換爲const-bool?

+0

哪個編譯器? const操作符int()const'編譯失敗 –

+0

編譯器是clang-3.4 – wimalopaan

+1

你可以更新問題標題以刪除雙重否定。我會自己做,但我不確定是否刪除「不」或「不」。甚至兩個? – icabod

回答

6

對引用綁定執行重載解析時,較少的cv限定類型是首選。這在13.3.3.2p3討論的,給定的例子:(13.3.3.1

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)的隱式對象參數是一個參考結合。4)。

爲了重載決議(13.3p2),轉換運算符被視爲成員函數(13.3.1.5)。上下文轉換爲bool具有初始化語義(4p4)。

重要的是,考慮到轉換運算符本身(13.3.3p1)之間的超載分辨率,在之後,轉換運算符的返回類型上所需的任何轉換僅被視爲

解決方案是確保所有轉換運算符具有相同的const資格,尤其是對標量類型。

+0

*「重要的是,轉換運算符的返回類型所需的任何轉換僅在考慮轉換運算符本身之間的重載解析(13.3.3p1)後纔會考慮。」*嗯,這是以*開頭的子彈「,上下文是初始化通過用戶定義的轉換「*這似乎意味着這是完全打算。 +1 – dyp

+0

@dyp這裏沒有UDCS,因爲我們沒有用'X'參數在不同函數之間進行解析。如果我們有'f(bool),將會有UDCSs; F(浮動); X x; f(x);'而且這些UDCS實際上是不明確的。 – ecatmur

+0

從'A'到'bool'的整個轉換是一個UDCS(在OP的例子中),但是重載解析被應用爲「太早」的恕我直言,其中UDC需要從'A'轉換爲'bool' isn沒有考慮,但僅用於定義可行的函數(因此只有SCS用於隱含對象參數才考慮用於重載分辨率)。 – dyp

4

將轉換爲非const-int優先級轉換爲const-bool的規則是什麼?

使用非const對象的const成員函數,需要將非const對象轉換爲const對象。這就是爲什麼operator int()operator bool() const有更好的匹配。

爲了使它更清楚一點,如果你想刪除INT運營商,真正與第一布爾上下文(第一IF)發生的情況是這樣的:

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

相反,會發生什麼情況是這樣的:

if (a.operator int()) 
+1

這個答案並沒有真正解決,因爲OPs問題中的註釋運算符也是顯式的,並且僅僅因爲const而改變了行爲。另外,顯式的'operator bool'可以不用在一個布爾上下文中進行轉換(比如'if')。這是在C++ 11中實現安全布爾方法的一種非常簡單的方法。 – Excelcius

+0

因此,要正確使用C++ 11中的expilicit-bool-idiom,必須實現operator bool()的const和非const版本。只是爲了防止其他轉換操作員踢? – wimalopaan

+0

我不太瞭解排名如何發生這種重載解決方案。通常,將某個'A'綁定到'A const&'是直接引用綁定,因此被視爲完全匹配。因此,在這兩種情況下,隱含對象參數都應該與隱式對象參數完全匹配。然後,兩者都有一個UDC,但是爲了轉換爲「int」,接下來是布爾轉換。顯然,這不是編譯器中發生的事情,隱含對象參數的匹配以某種方式排列不同。 – dyp

相關問題