user963241
user963241

Reputation: 7038

ClassType Conversions - operator + ambiguous

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

Answers (3)

johnsyweb
johnsyweb

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

Ben Voigt
Ben Voigt

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 conversions
  • int operator+ (int, int) -- requires one user-defined conversion and no standard conversions

You'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 conversion
  • int operator+ (const MyClass&, double) -- requires no conversions

Now 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 and long 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 types L and R.

Upvotes: 4

cpx
cpx

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

Related Questions