简体   繁体   English

Clang错误:static_cast的模糊转换

[英]Clang error: ambiguous conversion for static_cast

I have the following piece of code: 我有以下代码:

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 reports the following error: 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.

I can't figure out why is the compiler generating an error although I have the conversion operator defined and I make the conversion at that specific place explicit using static_cast<>. 我无法弄清楚为什么编译器会生成错误,尽管我已经定义了转换运算符,并且我使用static_cast <>在该特定位置进行显式转换。 The code passes compilation with GCC 4.5.2 and Visual Studio 2008 compilers. 该代码通过了GCC 4.5.2和Visual Studio 2008编译器的编译。 Clang version is 3.1, built by myself from the git repositories of Clang and LLVM a couple of days ago. Clang版本是3.1,几天前由我自己从Clang和LLVM的git存储库构建。

So, is Clang reporting an actual error? 那么,Clang是否报告了实际错误? And if yes, why is it an error as it's not obvious to me at all(I won't ask why the other compilers are silent about that)? 如果是的话,为什么它是一个错误,因为它对我来说并不明显(我不会问为什么其他编译器对此保持沉默)?

UPDATE: the sample code is now a small compilable example(sorry for not doing this from the first time) and replicating the real situation I have. 更新:示例代码现在是一个小的可编译示例(抱歉从第一次不这样做)并复制我的实际情况。 It seems that the conversion operator to AliasA is the problem, because if it's removed then everything compiles fine. 似乎AliasA的转换运算符是问题,因为如果它被删除,那么一切编译都很好。 The nasty thing right now is that for the above piece of code I get errors also from GCC. 现在令人讨厌的事情是,对于上面的代码我也从GCC得到错误。

UPDATE 2 : I added some code to the sample to reflect better my real situation; 更新2 :我在样本中添加了一些代码,以更好地反映我的实际情况; the only difference is that for the above sample I also get an error from GCC, whereas for my real code I don't. 唯一的区别是,对于上面的示例我也从GCC得到一个错误,而对于我的真实代码,我没有。

I have filed a bug report about this to clang. 我已经提交了一个有关此问题的错误报告。 They argue that it is not a bug. 他们认为这不是一个错误。 The C++ standard lacks a specification for this case and therefore the compiler reports it as ambiguous. C ++标准缺少此案例的规范,因此编译器将其报告为含糊不清。 See bug report . 查看错误报告

I think this behavior is counter-intuitive. 我认为这种行为是违反直觉的。 The first path through A::operator B() is a perfect match, while the second path involves three type conversions. 通过A ::运算符B()的第一条路径是完美匹配,而第二条路径涉及三种类型转换。 The only logical thing to do is to regard the perfect match as superior. 唯一合乎逻辑的做法是将完美匹配视为优秀。

What should a compiler do when a case is not explicitly resolved in the C++ standard? 在C ++标准中没有明确解决案例时,编译器应该怎么做?

  1. Produce an error message 产生错误消息
  2. Make a logical choice by analogy to other rules 通过类比其他规则做出合理的选择
  3. Contact the C++ standards committee and tell them to revise the standard. 联系C ++标准委员会并告诉他们修改标准。

?

There are two ways for static_cast to convert an A into a B: static_cast有两种方法将A转换为B:

  1. use A::operator B and call the implicit copy constructor B::B(const B& value) to create the new B 使用A::operator B并调用隐式复制构造函数B::B(const B& value)来创建新的B.

  2. use A::operator AliasA , convert the result to AliasB and call B::B(const AliasB& value) 使用A::operator AliasA ,将结果转换为AliasB并调用B::B(const AliasB& value)

The compiler does not know which way to prefer. 编译器不知道哪种方式更喜欢。 You can give a hint to use the second option by writing: 您可以通过编写以下内容来提示使用第二个选项:

    someFunc(counter, static_cast<AliasA>(someA));

To use the first option you can omit the cast by simply writing: 要使用第一个选项,您只需编写以下内容即可省略强制转换:

    someFunc(counter, someA);

Well, I'm not sure if the latter is well definined behaviour, but it works at least with gcc and msvc. 好吧,我不确定后者是否有明确的行为,但它至少与gcc和msvc一起工作。

I think I figured out in part what is happening, but I don't think I comprehend the whole situation. 我想我部分地想出了发生了什么,但我不认为我理解整个情况。 So the conversions paths the compiler sees look like below: 所以编译器看到的转换路径如下所示:

              /--------  A  --------\
              |                     |
              |                     |
              B             AliasA(unsigned short)
              |                     |
              |                     |
      copy ctor of B            AliasB(int)
                                    |
                                    |
                           ctor B(const AliasB& value)

So it makes sense and the compiler is right in reporting the ambiguity (I love clan'g error and warning messages). 所以它是有道理的,编译器正确报告歧义 (我喜欢clan'g错误和警告消息)。 One way to make it work is to break the conversion path via the AliasA(see the comments marked with (*) in the sample code in the question). 使其工作的一种方法是通过AliasA中断转换路径(请参阅问题中示例代码中标有(*)的注释)。 It also works if I break the offending expression and rely only on implicit conversion, not trying to explicitly static_cast<> anything( see the comments marked with (**) in the sample code in the question). 如果我打破有问题的表达式并仅依赖于隐式转换,而不是尝试显式static_cast <>任何东西(请参阅问题中示例代码中标有(**)的注释 ,它也可以工作。 But I don't grasp completely what's happening behind the scenes. 但我并不完全掌握幕后发生的事情。 I still don't understand completely why it behaves different in the (**) case because the conversion paths seem to be the same, at least for the "theB.combine(high())" part. 我仍然不完全理解为什么它在(**)情况下表现不同,因为转换路径似乎是相同的,至少对于“theB.combine(high())”部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM