13

考慮簡單的代碼:重載決策具有多種功能和多種轉換操作符

#include<iostream> 

struct A { 
    operator double(){ 
     std::cout<<"Conversion function double chosen."<<std::endl; 
     return 1.1; 
    } 
    operator char(){ 
     std::cout<<"Conversion function char chosen."<<std::endl; 
     return 'a'; 
    } 
} a; 

void foo(int){} 
void foo (char){} 
int main() { 
    foo(a); 
} 

上面的代碼工作的罰款,並如預期GCC,鐺和VC++選擇foo(char)

現在,讓我們修改代碼點點:

#include<iostream> 

struct A { 
    operator double(){ 
     std::cout<<"Conversion function double chosen."<<std::endl; 
     return 1.1; 
    } 
    operator char(){ 
     std::cout<<"Conversion function char chosen."<<std::endl; 
     return 'a'; 
    } 
} a; 

void foo(int){} 
void foo (double){} //parameter changed from char to double 
int main() { 
    foo(a); 
} 

現在,這個應該有選擇foo(double),但似乎只有VC++而鐺和GCC不滿意上面的代碼是高興的代碼。

main.cpp:11:10: error: call of overloaded 'foo(A&)' is ambiguous 
foo(a); 
    ^
main.cpp:8:6: note: candidate: void foo(int) 
void foo(int){} 
    ^
main.cpp:9:6: note: candidate: void foo(double) 
void foo (double){} //parameter changed from char to double 
    ^

任何人都可以解釋爲什麼上面的代碼失敗?還是它的bug?

還有一個問題:gcc和clang共享重載分辨率的代碼嗎?

+2

1:定義「不快樂」。 2:如果刪除'foo(int)'會發生什麼? – Amit

+2

@Amit不快樂意味着代碼被拒絕,並且至於刪除函數「foo(int)」,這不是問題的一部分,您可以自己嘗試。 –

+1

@AngelusMortis:VC++選擇哪個函數? – davidhigh

回答

4

TL; DR:不同的是,在第一種情況下,相對於所述第二,用戶定義的轉換序列(A -> charA -> int)調用相同的轉換函數(operator char)。這使我們能夠通過[over.ics.rank] /(3.3)打破平局。


最好轉換運算符用於特定功能由[over.match.best]/(1.4)選擇(比較它們的返回類型的轉換序列)。

因此,對於foo(int)更好的轉換功能是operator char後跟一個晉升爲int,相對於operator double後跟一個浮點轉換。

現在考慮的第二個重載的這兩種型號:

  1. 最好的ICS foo(char)也通過operator char(身份比浮點轉換更好)。因此[over.ics.rank]/(3.3)適用:

    用戶定義的轉換序列U1比另一用戶定義的轉換序列的更好的轉換序列U2如果它們包含相同的用戶定義的轉換函數 [...]和在任一情況下的第二標準轉換序列U1比第二標準轉換序列U2更好。

    因此,整體轉換爲F2被認爲是更好的,它被選中。

  2. 最好的ICS到foo(double)通過operator double。我們最終得到兩個採用不同轉換函數的轉換序列;沒有什麼是真的適用的,我們只是含糊不清。

5

A -> charA -> char

A -> intA -> char -> int(因爲charint是推廣等等摔打doubleint轉換)。

A -> doubleA -> double

兩個用戶定義的轉換序列只有在涉及相同的用戶定義的轉換函數時才具有可比性。因此,A -> char是比A -> int更好的轉換順序,因此您的第一個案例是明確的。 A -> intA -> double都不如其他,所以第二種情況是不明確的。