CAUSE
In the following sample, the line where the error is generated has the
form:
int + Fraction
Because there is no exact match to the operators provided for this
operation, a set of candidate operator + must be determined.
First, there are the user-supplied operators:
+ ( long, const Fraction& )
+ ( const Fraction&, long )
+ ( const Fraction&, const Fraction& )
Second, there are the built-in operators:
+ ( int, float )
The above is chosen because it is "int" plus an arbitrary type, and
the Fraction object can be converted only to a "float".
Now, the candidate selection list is:
+ ( long, const Fraction& )
+ ( const Fraction&, long )
+ ( const Fraction&, const Fraction& )
+ ( int, float )
Because there is more than one choice, the overload disambiguation
takes place.
The first argument is considered:
+ ( long, ... ) Requires one standard conversion.
+ ( const Fraction&, ... ) Requires one user-defined conversion.
+ ( int, ... ) Is an exact match.
Therefore, the set of best candidates for the first argument consists
of:
+ ( int, float )
Then the second argument is considered:
+ ( ..., const Fraction& ) Requires only trivial conversions.
+ ( ..., long ) Requires 1 user-defined conversion and
one standard conversion.
+ ( ..., float ) Requires one user-defined conversion.
Therefore, the set of best candidates for the second argument consists
of:
+ ( const Fraction&, const Fraction& )
+ ( long, const Fraction& )
The intersection of these two sets is NULL, it contains nothing,
and therefore the operation is ambiguous.
RESOLUTION
- Typecast the operand that is causing the ambiguity. For example:
c = 1234L + a;
c = (long)1234 + a;
- Remove the float operator from the Fraction class. This prevents a
default operator "+" from being provided by the compiler because
there is no conversion provided by the user for the second
argument. The selection is made from the list of three
user-provided "+" operators.
For the first argument, the first operator
+ ( long, const Fraction& )
is chosen because a trivial conversion is required for int to long.
The same selection is also made for the second argument, making the
operator
+ ( long, const Fraction& )
common to both the selections, and thus resolving the ambiguity.
Sample Code
/* Compile Options needed: none
*/
class Fraction {
private:
int x;
int y;
public:
Fraction(int a=0, int b=0) : x(a), y(b) { }
~Fraction(){}
operator float () {return int(x);}
};
Fraction& operator+(long i, const Fraction& ) { Fraction f ; return f; }
Fraction& operator+(const Fraction& , const Fraction& ){ Fraction f;
return f; }
Fraction& operator+(const Fraction& , long i ) { Fraction f ; return f;}
void main()
{
Fraction a(2,3), c;
c = 1234 + a; // error C2666: '+' : 4 overloads have
// similar conversion
}