[英]Clang error: ambiguous conversion for static_cast
我有以下代碼:
typedef int AliasB;
typedef unsigned short AliasA;
class Alias
{
public:
explicit Alias(int someInt) { }
};
// (*) !! below breaks the conversion path via AliasA !!
//typedef Alias AliasA;
class C
{
public:
C() { }
};
class B
{
public:
B() { }
B(const AliasB& value) { }
operator AliasB() const
{
return -1000;
}
C combine(const B& someB)
{
return C();
}
};
class A
{
public:
A() { }
operator B() const
{
return B();
}
operator AliasA() const
{
return 1001;
// (*) !! below breaks the conversion path via AliasA !!
//return AliasA(1000);
}
A high()
{
return A();
}
A low()
{
return A();
}
C process()
{
return (static_cast<B>(low())).combine(static_cast<B>(high()));
// (**) !! the below compiles fine !!
//B theB = low();
//return theB.combine(high());
}
};
inline int someFunc(unsigned int someParam, const B& bParam)
{
return 1;
}
inline A createSomeA()
{
return A();
}
int main ()
{
A someA;
unsigned int counter = 200;
someFunc(counter, someA);
//someFunc(counter, static_cast<B>(createSomeA()));
someA.process();
return 0;
}
Clang報告以下錯誤:
clang_static_test.cpp:66:17: error: ambiguous conversion for static_cast from 'A' to 'B'
return (static_cast<B>(low())).combine(static_cast<B>(high()));
^~~~~~~~~~~~~~~~~~~~~
clang_static_test.cpp:21:7: note: candidate is the implicit copy constructor
class B
^
clang_static_test.cpp:25:5: note: candidate constructor
B(const AliasB& value) { }
^
clang_static_test.cpp:66:48: error: ambiguous conversion for static_cast from 'A' to 'B'
return (static_cast<B>(low())).combine(static_cast<B>(high()));
^~~~~~~~~~~~~~~~~~~~~~
clang_static_test.cpp:21:7: note: candidate is the implicit copy constructor
class B
^
clang_static_test.cpp:25:5: note: candidate constructor
B(const AliasB& value) { }
^
2 errors generated.
我無法弄清楚為什么編譯器會生成錯誤,盡管我已經定義了轉換運算符,並且我使用static_cast <>在該特定位置進行顯式轉換。 該代碼通過了GCC 4.5.2和Visual Studio 2008編譯器的編譯。 Clang版本是3.1,幾天前由我自己從Clang和LLVM的git存儲庫構建。
那么,Clang是否報告了實際錯誤? 如果是的話,為什么它是一個錯誤,因為它對我來說並不明顯(我不會問為什么其他編譯器對此保持沉默)?
更新:示例代碼現在是一個小的可編譯示例(抱歉從第一次不這樣做)並復制我的實際情況。 似乎AliasA的轉換運算符是問題,因為如果它被刪除,那么一切編譯都很好。 現在令人討厭的事情是,對於上面的代碼我也從GCC得到錯誤。
更新2 :我在樣本中添加了一些代碼,以更好地反映我的實際情況; 唯一的區別是,對於上面的示例我也從GCC得到一個錯誤,而對於我的真實代碼,我沒有。
我已經提交了一個有關此問題的錯誤報告。 他們認為這不是一個錯誤。 C ++標准缺少此案例的規范,因此編譯器將其報告為含糊不清。 查看錯誤報告 。
我認為這種行為是違反直覺的。 通過A ::運算符B()的第一條路徑是完美匹配,而第二條路徑涉及三種類型轉換。 唯一合乎邏輯的做法是將完美匹配視為優秀。
在C ++標准中沒有明確解決案例時,編譯器應該怎么做?
?
static_cast
有兩種方法將A轉換為B:
使用A::operator B
並調用隱式復制構造函數B::B(const B& value)
來創建新的B.
使用A::operator AliasA
,將結果轉換為AliasB並調用B::B(const AliasB& value)
編譯器不知道哪種方式更喜歡。 您可以通過編寫以下內容來提示使用第二個選項:
someFunc(counter, static_cast<AliasA>(someA));
要使用第一個選項,您只需編寫以下內容即可省略強制轉換:
someFunc(counter, someA);
好吧,我不確定后者是否有明確的行為,但它至少與gcc和msvc一起工作。
我想我部分地想出了發生了什么,但我不認為我理解整個情況。 所以編譯器看到的轉換路徑如下所示:
/-------- A --------\
| |
| |
B AliasA(unsigned short)
| |
| |
copy ctor of B AliasB(int)
|
|
ctor B(const AliasB& value)
所以它是有道理的,編譯器正確報告歧義 (我喜歡clan'g錯誤和警告消息)。 使其工作的一種方法是通過AliasA中斷轉換路徑(請參閱問題中示例代碼中標有(*)的注釋)。 如果我打破有問題的表達式並僅依賴於隱式轉換,而不是嘗試顯式static_cast <>任何東西(請參閱問題中示例代碼中標有(**)的注釋) ,它也可以工作。 但我並不完全掌握幕后發生的事情。 我仍然不完全理解為什么它在(**)情況下表現不同,因為轉換路徑似乎是相同的,至少對於“theB.combine(high())”部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.