Here is how the code looks:
using namespace std;
class dummy{
public:
int x;
explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
};
class myClass {
public:
operator int(); //<---problematic conversion
explicit operator dummy();
};
myClass::operator int() {
return 10;
}
myClass::operator dummy(){
return dummy(9);
}
int main() {
myClass mc1;
dummy val = (dummy)mc1;
cout << "mc1 int cast: " << mc1 << endl;
cout << "val.x: :" << val.x << endl;
std::cin.get();
return 0;
}
I'm using ms vs compiler here and getting c2440 (type cast error). To my understanding, I'm not doing anything wrong syntax-wise. The problem here is that it works fine if I remove the implicit conversion: operator int()
and its respective function out of the code.
ie:
using namespace std;
class dummy{
public:
int x;
explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
};
class myClass {
public:
//operator int();
explicit operator dummy();
};
/*
myClass::operator int() {
return 10;
}*/
myClass::operator dummy(){
return dummy(9);
}
int main() {
myClass mc1;
dummy val = (dummy)mc1;
//cout << "mc1 int cast: " << mc1 << endl;
cout << "val.x: " << val.x << endl;
std::cin.get();
return 0;
}
this will produce the following output (as expected):
val.x: 9
Edit: explicit keyword was missing in the second example. The output is the same
Compiling your original code with gcc-9 on ubuntu 18.04 I get this:
test.cpp:27:24: error: call of overloaded ‘dummy(myClass&)’ is ambiguous
27 | dummy val = (dummy)mc1;
| ^~~
test.cpp:7:14: note: candidate: ‘dummy::dummy(int)’
7 | explicit dummy(int x = 0) : x{ this->x = x } {}; //explicit has no effect here
| ^~~~~
test.cpp:4:7: note: candidate: ‘constexpr dummy::dummy(const dummy&)’
4 | class dummy{
| ^~~~~
test.cpp:4:7: note: candidate: ‘constexpr dummy::dummy(dummy&&)’
What is happening is the compiler cannot tell if you want to create a new 'dummy' class out of the int conversion of 'myClass' or a new 'dummy' out of the implicitly generated copy operator of 'dummy'.
This causes a loop where 'myClass' can be converted to both int
and dummy
which means that compiler gets stuck trying to convert 'myClass' since it doesnt know what you actually want to do - convert to 'dummy', convert to 'dummy' then copy it, or make a new 'dummy' by converting 'myClass' to int
The solution to this is to make your conversion operator to int explicit
this prevents implicit conversion by the compiler and allows this to work (at least on gcc-9).
This is an updated copy of your code which will work:
using namespace std;
class dummy{
public:
int x;
explicit dummy(int x=0) : x(x) {}
};
class myClass {
public:
explicit operator int(); // < Set to explicit
explicit operator dummy();
};
myClass::operator int() {
return 10;
}
myClass::operator dummy(){
return dummy(9);
}
int main() {
myClass mc1;
dummy val = static_cast<dummy>(mc1);
cout << "mc1 int cast: " << static_cast<int>(mc1) << endl;
cout << "val.x: :" << val.x << endl;
std::cin.get();
return 0;
}
This compiles with gcc-9 and clang++-9
As a side note please please please never use C style casts in C++, they are error prone and a pain in the ass to debug