Clang错误:static_cast的模糊转换

cel*_*vek 6 c++ casting clang

我有以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚为什么编译器会生成错误,尽管我已经定义了转换运算符,并且我使用static_cast <>在该特定位置进行显式转换.该代码通过了GCC 4.5.2和Visual Studio 2008编译器的编译.Clang版本是3.1,几天前由我自己从Clang和LLVM的git存储库构建.

那么,Clang是否报告了实际错误?如果是的话,为什么这是一个错误,因为它对我来说并不明显(我不会问为什么其他编译器对此保持沉默)?

更新:示例代码现在是一个小的可编译示例(抱歉从第一次不这样做)并复制我的实际情况.似乎AliasA的转换运算符是问题,因为如果它被删除,那么一切编译都很好.现在令人讨厌的事情是,对于上面的代码我也从GCC得到错误.

更新2:我在样本中添加了一些代码,以更好地反映我的实际情况; 唯一的区别是,对于上面的示例我也从GCC得到一个错误,而对于我的真实代码,我没有.

cel*_*vek 0

我想我部分地了解了正在发生的事情,但我不认为我理解了整个情况。因此编译器看到的转换路径如下所示:

              /--------  A  --------\
              |                     |
              |                     |
              B             AliasA(unsigned short)
              |                     |
              |                     |
      copy ctor of B            AliasB(int)
                                    |
                                    |
                           ctor B(const AliasB& value)
Run Code Online (Sandbox Code Playgroud)

所以这是有道理的,编译器在报告歧义方面是正确的(我喜欢 clan'g 错误和警告消息)。使其工作的一种方法是通过 AliasA 中断转换路径(请参阅问题示例代码中标有(*)的注释)。如果我破坏有问题的表达式并仅依赖隐式转换,而不是尝试显式 static_cast<> 任何内容(请参阅问题示例代码中标有(**)的注释),它也有效。但我并不完全了解幕后发生的事情。我仍然不完全理解为什么它在(**)情况下表现不同,因为转换路径似乎是相同的,至少对于“theB.combine(high())”部分而言。