Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang error: ambiguous conversion for static_cast

Tags:

c++

casting

clang

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_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<>. The code passes compilation with GCC 4.5.2 and Visual Studio 2008 compilers. Clang version is 3.1, built by myself from the git repositories of Clang and LLVM a couple of days ago.

So, is Clang reporting an actual error? 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. The nasty thing right now is that for the above piece of code I get errors also from GCC.

UPDATE 2: I added some code to the sample to reflect better my real situation; the only difference is that for the above sample I also get an error from GCC, whereas for my real code I don't.

like image 566
celavek Avatar asked Mar 28 '12 11:03

celavek


1 Answers

There are two ways for static_cast to convert an A into a B:

  1. use A::operator B and call the implicit copy constructor B::B(const B& value) to create the new B

  2. use A::operator AliasA, convert the result to AliasB and call 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.

like image 142
Stephan Avatar answered Oct 23 '22 03:10

Stephan