C ++ The overload operator bool () gives an ambiguous overload error using the + operator

I am compiling some C ++ code of the MegaInt class, which is a positive decimal type class that allows arithmetic operations on huge numbers.

I want to overload the bool statement to allow code like this:

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

This is what I did:

Title:

 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 what I am doing:

 MegaInt(3424324234234342) + 5; 

This gives me this error:

ambiguous overloading for 'operator +' to 'operator + (const MegaInt &, const MegaInt &) Note: candidates: operator + (int, int) | Note: const megaInt + operator (const MegaInt &, const MegaInt &) |

I do not know why. How does overloaded bool () call the + operator, becomes ambiguous? ΒΈ

Thanks.


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

Both void * and Idoom Safe Bool work. Except for one tiny problem, I hope there is a workaround:

When comparing with 0 as:

 if (aMegaInt == 0) 

The compiler returns an ambiguous overload error again. I understand why: he does not know whether we are comparing the values ​​0 with false or with MegaInt. However, in this case, I would like it to be translated into MegaInt (0). Is there any way to force this?

Thanks again.

+6
c ++ operator-overloading boolean
source share
6 answers

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

A way to solve this problem is to use the safe idiom bool .

Technically, creating an operator void* is not an example of a safe bool idiom, but in practice it is quite safe, because the bool / int problem you are working with is a common mistake, and ruined some completely reasonable and otherwise correct code ( as you can see from your question), but the misuse of the void* transform is not so common.

+10
source share

The wikipedia entry for explicit conversion operators for C ++ 0x has a decent summary of why you see this pre-C ++ 0x error.In principle, the bool conversion operator is an integral type of conversion, so it will be used in an integral arithmetic expression. The pre-C ++ 0x fix should instead use void * as the conversion operator; void * can be converted to a logical expression, but not to an integral expression.

+3
source share

As the Erik answers say, the problem is that by providing an implicit conversion to bool , you open the door to expressions that can mean a few things; in this case, the compiler will complain about the ambiguity and give your error.

However, note that providing an implicit conversion to void* will not let you disconnect; it will simply change the set of expressions that represent the problem.

There are two airtight solutions in this matter:

  • Make conversion to bool explicit (which may be undesirable if the class represents an object with an intuitive value of "true / false")
  • Use the safe idiom bool (it really covers all the bases, but so many good things in life and C ++ are too complicated - you pay the price)
+2
source share
 MegaInt(3424324234234342) + 5; MegaInt + int; 

Should the compiler convert your MegaInt to an integral (bool is an integral type) or an integer to MegaInt (do you have an int constructor)?

Fix this by creating operator void * instead of operator bool :

operator void *() const { return (*this != 0) ? ((void *) 1) : ((void *) 0); }

0
source share

The problem is that bool is free to convert to int . Thus, the expression MegaInt(3424324234234342) + 5; can be correctly interpreted as follows:

 (bool)(MegaInt(3424324234234342)) + 5; 

or

 MegaInt(3424324234234342) + MegaInt(5); 

Each of these expressions includes one user-defined transformation and are equal in the eyes of the compiler. For this reason, converting to bool is very problematic. It would be nice to have a way of saying that this should only happen in a context that bool explicitly requires, but it doesn't exist .: - /

Converting to void * , which someone else is proposing, is a workaround, but I think it has its problems as a workaround, and I would not do that.

0
source share

Others mentioned Idiom Safe Bool. However, for objects like yours, it is a bad idea to add all this nasty, special logic when you need full algebra support.

You determine the type of custom integer. You get a lot more effort by defining "operator ==" and "operator! =", Then implementing "operator bool ()" is something like:

 operator bool() { return (*this != 0); } 

Only from these three functions do you get all the "if" idioms for integers, and they will behave the same for your custom ints as built-in: "if (a == b)", "if (a! = B)", " if (a) "," if (! a) ". Your implicit "bool" rule also (and if you are careful) also works intuitively.

In addition, the full Safe Bool Idiom is not needed. Think about it - the only time you need it: "1) poor definition of two objects or undefined, 2) to be protected (int) or other primitive types, and 3) the reliability of the object - (the actual source of the returned bool).

Well, 2) is only a consideration if you really want to SUPPORT casting to a numeric type of type int or float. But for objects that do not have a clear idea of ​​equality (No. 1), the provision of such garbage inevitably creates the risk that the "logical bomb" if (a == b) "supposedly protects you from the idiom." Just declare "operator int ()" and private ones like you, with a copy of ctor on non-copied objects and do with it:

 class MyClass { private: MyClass(const MyClass&); operator int(); operator long(); // float(), double(), etc. ... public: // ctor & dtor .. bool operator==(const MyClass& other) const { //check for equality logic... } bool operator!=(const MyClass& other) const { return !(*this == other); } operator bool() { return (*this != 0); } }; 
0
source share

All Articles