Reputation: 7038
In the following, I'm expecting obj
to be converted to an int
but why does it returns operator + ambiguous in the following?
class MyClass
{
public:
MyClass(int X = 0, double Y = 0):x(X), y(Y){}
operator int() const { return x; }
operator double() const { return y; }
private:
int x;
double y;
};
int main()
{
MyClass obj(10, 20);
int x = obj + 5; //obj converted to int
}
Upvotes: 2
Views: 215
Reputation: 141780
Of course, you could solve this by overloading the +
operator
within MyClass
(as opposed to the global one in Ben Voigt's answer):
int operator +(const int rhs) const
{
return x + rhs;
}
int operator +(const double rhs) const
{
return y + rhs;
}
Tidy and unambiguous.
Upvotes: 1
Reputation: 283614
Because both conversions are equivalent, it's ambiguous. Remember that the C++ language directly defines +
for arguments of double
and int
, there is no standard conversion involved.
So neither of these functions is better than the other:
double operator+ (double, int)
-- requires one user-defined conversion and no standard conversionsint operator+ (int, int)
-- requires one user-defined conversion and no standard conversionsYou'll need to provide all the usual arithmetic operators yourself, if you want to make this work, and not rely on implicit conversion operators.
double operator+ (const MyClass&, int)
-- requires one standard conversionint operator+ (const MyClass&, double)
-- requires no conversionsNow obj + 5
will have an unambiguous best match.
C++0x draft n3245 says, in section [over.built]
- In this subclause, the term promoted integral type is used to refer to those integral types which are preserved by integral promotion (including e.g.
int
andlong
but excluding e.g.char
). Similarly, the term promoted arithmetic type refers to floating types plus promoted integral types.For every pair of promoted arithmetic types L and R, there exist candidate operator functions of the form
LR operator*(L, R); LR operator/(L, R); LR operator+(L, R); LR operator-(L, R); bool operator<(L, R); bool operator>(L, R); bool operator<=(L, R); bool operator>=(L, R); bool operator==(L, R); bool operator!=(L, R);
where
LR
is the result of the usual arithmetic conversions between typesL
andR
.
Upvotes: 4
Reputation: 17557
You need do an explicit cast to instruct the compiler that you do really want an integer.
int x = static_cast<int>(obj) + 5; //obj converted to int
Upvotes: 1