簡體   English   中英

Clang錯誤:static_cast的模糊轉換

[英]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 ++標准中沒有明確解決案例時,編譯器應該怎么做?

  1. 產生錯誤消息
  2. 通過類比其他規則做出合理的選擇
  3. 聯系C ++標准委員會並告訴他們修改標准。

static_cast有兩種方法將A轉換為B:

  1. 使用A::operator B並調用隱式復制構造函數B::B(const B& value)來創建新的B.

  2. 使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM