Visual C++ 2012.代碼。我認爲它應該編譯;編者尊重地不同意。我已將範圍縮小到:在VC++ 2012中意外模糊的重載分辨率
struct B { };
void foo(B* b, signed int si) { } // Overload 1
void foo(B const* b, unsigned int ui) { } // Overload 2
int main()
{
B b;
unsigned int ui;
foo(&b, ui);
}
因此,我們有兩個重載解決方案的候選人。對於第一個重載,第一個參數完全匹配,第二個參數需要整數轉換(無符號簽名)。對於第二個重載,第二個參數完全匹配,並且第一個參數需要cv調整(因爲&b
是指向非const的指針)。
現在,這似乎應該是完全無歧義的。對於重載1,第一個參數是標準關於重載分辨率部分定義的「完全匹配」,但第二個參數是「轉換」。對於超載2,兩個參數都是「完全匹配」(資格轉換與身份相同)。因此(我顯然是不完美的推理),應該選擇過載2,沒有歧義。還有:
a.cpp(12): error C2666: 'foo' : 2 overloads have similar conversions
a.cpp(6): could be 'void foo(const B *,unsigned int)'
a.cpp(5): or 'void foo(B *,int)'
while trying to match the argument list '(B *, unsigned int)'
note: qualification adjustment (const/volatile) may be causing the ambiguity
GCC在默認方言和C++ 11(謝謝IDEOne!)中都看起來不錯。所以我傾向於把這個問題歸咎於MSVC中的一個錯誤,但是(a)你知道他們對那些認爲他們的bug是編譯器bug的人的評價,以及(b)這看起來像是一個非常明顯的錯誤,它們在一致性測試期間會發出紅旗。
這是一個不兼容的MSVC或不兼容的GCC? (或兩者?)我的理由是超負荷分辨率的聲音?
我不知道哪個編譯器是正確的,但作爲一個人,我更喜歡知道使用哪個重載,而不必基於兩種類型轉換的「優先級」來消除歧義:-) – Cameron 2014-09-02 13:18:29
@Cameron哦,我同意。實際的用例更有意義,並且*看起來*毫不含糊。 – Sneftel 2014-09-02 13:24:45