C++ Overload operator bool() gives an ambiguous overload error with operator+

booleancoperator-overloading

I'm compiling some c++ code of a class MegaInt which is a positive decimal type class that allows arithmetic operations on huge numbers.

I want to overload operator bool to allow code like this:

MegaInt m(45646578676547676);  
if(m)  
    cout << "YaY!" << endl;

This is what I did:

header:

class MegaInt
{
    public:
        ...
    operator bool() const;
};

const MegaInt operator+(const MegaInt & left, const MegaInt & right);
const MegaInt operator*(const MegaInt & left, const MegaInt & right);

implementation:

MegaInt::operator bool() const
{
    return *this != 0;
}
const MegaInt operator+(const MegaInt & left, const MegaInt & right)
{
    MegaInt ret = left;
    ret += right;
    return ret;
}

Now, the problem is if I do:

MegaInt(3424324234234342) + 5;

It gives me this error:

ambiguous overload for 'operator+' in 'operator+(const MegaInt&, const MegaInt&)
note: candidates are: operator+(int, int) |
note: const MegaInt operator+(const MegaInt&, const MegaInt&)|

I don't know why. How is the overloaded bool() causing operator+ to become ambiguous?ΒΈ

Thank You.


Well, everyone gave me great answers, unfortunately, none of them seem to solve my problem entirely.

Both void* or the Safe Bool Idiom works. Except for one tiny problem, I hope has a workaround:

When comparing with 0 like:

if (aMegaInt == 0)

The compiler gives an ambiguous overload error again. I understand why: it doesn't know if we're comparing to false or to MegaInt of value 0. None the less, in that case, I'd want it to cast to MegaInt(0). Is there a way to force this?

Thank You Again.

Best Answer

The C++ compiler is allowed to automatically convert bool into int for you, and that's what it wants to do here.

The way to solve this problem is to employ the safe bool idiom.

Technically, creating an operator void* is not an example of the safe bool idiom, but it's safe enough in practice, because the bool/int problem you're running into is a common error, and messes up some perfectly reasonable and otherwise correct code (as you see from your question), but misuses of the void* conversion are not so common.

Related Topic