I've got 2 very simple classes, ClassA and ClassB. I want to be able to cast from ClassB to ClassA. Using Sun C++ 5.11, it compiles fine and runs exactly as I expect it to, according to this: Conversion constructor vs. conversion operator: precedence.
When I try to compile it using gcc version 4.8.2, it gives an error about an ambiguous call to overloaded function. Why would this behave differently when casting appears to be a fairly well-defined behaviour?
The Code:
main.cc
#include <iostream>
class ClassB;
class ClassA
{
public:
ClassA( const int& num )
: _number( num )
{ std::cout << "ClassA int constructor\n"; }
private:
int _number;
};
class ClassB
{
public:
ClassB( const int& num )
: _number( num )
{ std::cout << "ClassB int constructor\n"; }
operator ClassA() const throw()
{
std::cout << "ClassB operator ClassA()\n";
return ClassA( _number );
}
operator int() const throw()
{
std::cout << "ClassB operator int()\n";
return _number;
}
private:
int _number;
};
int main( int argc, const char* argv[] )
{
std::cout << "Creating b:\n";
ClassB b( 5 );
std::cout << "Casting b to a ClassA:\n";
ClassA a = static_cast<ClassA>( b );
}
Using Sun C++ 5.11, it compiles fine and spits out the following output:
Creating b:
ClassB int constructor
Casting b to a ClassA:
ClassB operator ClassA()
ClassA int constructor
Using gcc, the compiler spits out the following error:
main.cc: In function 'int main(int, const char**)':
main.cc:43:36: error: call of overloaded 'ClassA(ClassB&)' is ambiguous
ClassA a = static_cast<ClassA>( b );
^
main.cc:43:36: note: candidates are:
main.cc:8:2: note: ClassA::ClassA(const int&)
ClassA( const int& num )
^
main.cc:5:7: note: ClassA::ClassA(const ClassA&)
class ClassA
If I comment out ClassB::operator int() or ClassA::ClassA( const int& ), it compiles fine and gives the same output. If I comment out ClassB::operator CLassA(), I get the following output:
Creating b:
ClassB int constructor
Casting b to a ClassA:
ClassB operator int()
ClassA int constructor
Why does gcc consider these two conversion sequences equivalent:
ClassB::operator ClassA()
ClassB::operator int() -> ClassA::ClassA( const int& )