In the program below, class A has a convert-to-int operator. Class B has a convert-to-A operator. While the compiler converts A to int implicitly, it fails to do so for converting B to A:
class A
{
protected:
int _a{0};
public:
A(int a) : _a(a) {}
operator int() const {return _a;}
A operator-(const A& rhs) const {return _a - rhs._a;}
};
class B
{
protected:
int _b{0};
public:
B(int b) : _b(b) {}
operator A() const {return _b;}
};
int main()
{
A a(1);
B b(2);
auto x = 2 - a; // Ok
auto y = b - a; // error: no match for ‘operator-’ (operand types are ‘B’ and ‘A’)
return 0;
}
Why does it behave like this?
User-defined conversions on the implicit object parameter of a function are explicitly not allowed in overload resolution.
Because your operator- is defined as member of the class, the left-hand side of - is the implicit object parameter. No attempt will be made to use a user-defined conversion on the argument/operand provided for it, your conversion function from B to A being such a user-defined conversion.
For what it is worth, the built-in - is considered in overload resolution as if there were free operator- overloads taking corresponding built-in types as parameter, which is why there user-defined conversions are permitted on both sides of - and the built-in operator-(int, int) overload is viable for 2 - a.
If you implement your operator- as a free function outside the class, it will work as you expect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With