Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No implicit conversion in overloaded operator

d1 + 4 works but 4 + d1 doesn't even though 4 can be converted implicitly to a GMan. Why aren't they equivalent?

struct GMan
{
    int a, b;

    GMan() : a(), b() {}
    GMan(int _a) : a(_a), b() {}
    GMan(int _a, int _b) : a(_a), b(_b) {}

    GMan operator +(const GMan& _b)
    {
         GMan d;
         d.a = this->a + _b.a;
         d.b = this->b + _b.b;
         return d;
    }
};

int main()
{
    GMan d1(1, 2), d(2);
    GMan d3;
    d3 = d1 + 4; 
    d3 = 4 + d1;
}
like image 738
GMan's Fan Avatar asked Nov 12 '10 13:11

GMan's Fan


People also ask

What are the three rules for defining an overloaded casting operator function?

1) Only built-in operators can be overloaded. New operators can not be created. 2) Arity of the operators cannot be changed. 3) Precedence and associativity of the operators cannot be changed.

What is implicit overloading?

Yes, there is something called implicit operator overloading. According to MSDN, an implicit keyword is used to declare an implicit user-defined type conversion operator. In other words, this gives the power to your C# class, which can accepts any reasonably convertible data type without type casting.

Can we change the behavior of overloaded operator?

No! If you want to overload an operator, the argument of your operator must contain at least one user-defined type. For example, in this case, you can overload minus for an integer and a class.

Why operator overloading is not possible in Java?

Java doesn't supports operator overloading because it's just a choice made by its creators who wanted to keep the language more simple. Every operator has a good meaning with its arithmetic operation it performs. Operator overloading allows you to do something extra than what for it is expected for.


2 Answers

A call x + y is translated by the C++ compiler into either of the following two calls (depending on whether x is of class type, and whether such a function exists):

  1. Member function

    x.operator +(y);
    
  2. Free function

    operator +(x, y);
    

Now C++ has a simple rule: no implicit conversion can happen before a member access operator (.). That way, x in the above code cannot undergo an implicit conversion in the first code, but it can in the second.

This rule makes sense: if x could be converted implicitly in the first code above, the C++ compiler wouldn’t know any more which function to call (i.e. which class it belongs to) so it would have to search all existing classes for a matching member function. That would play havoc with C++’ type system and make the overloading rules even more complex and confusing.

like image 99
Konrad Rudolph Avatar answered Nov 03 '22 03:11

Konrad Rudolph


This answer is correct. Those points then entail the canonical way of implementing such operators:

struct GMan
{
    int a, b;

    /* Side-note: these could be combined:
    GMan():a(),b(){}
    GMan(int _a):a(_a),b(){}
    GMan(int _a, int _b):a(_a),b(_b){}
    */
    GMan(int _a = 0, int _b = 0) : a(_a), b(_b){} // into this

    // first implement the mutating operator
    GMan& operator+=(const GMan& _b)
    {
        // the use of 'this' to access members
        // is generally seen as noise
        a += _b.a;
        b += _b.b;

        return *this;
    }
};

// then use it to implement the non-mutating operator, as a free-function
// (always prefer free-functions over member-functions, for various reasons)
GMan operator+(GMan _a, const GMan& _b)
{
    _a += b; // code re-use
    return _a;
}

And so on for other operators.

like image 41
GManNickG Avatar answered Nov 03 '22 02:11

GManNickG