2
class MyClass {
public:
    MyClass(int){}

};
MyClass operator +(MyClass& lOperand, MyClass& rOperand) {
    return lOperand;
}

int main() {
    MyClass obj1(0);
    obj1 = obj1 + 2;  // 1
}

Here compiler says no match function of operator + in line 1. But I think 2 can be converted to a MyClass object as the constructor of MyClass is not explicit. If I take & away from the parameter, then it is OK.

  • 2
    Try `const` for the parameters. – πάντα ῥεῖ Jun 20 '22 at 17:36
  • 1
    Use `const` so that `const MyClass& rOperand` can bind to 2 which is an rvalue. Non-const lvalue references (`MyClass& rOperand`) cannot bind to rvalues. – digito_evo Jun 20 '22 at 17:40
  • `MyClass operator +(MyClass&, MyClass&)` This signature tells me "two parameter by reference, *which will be modified*, and return a MyClass by value." Why would you want to modify either parameter in a binary `+` operation? That'd be very surprising behavior. And upon further investigation, the routine does **not** actually modify those parameters. In the code review, I'd ask: Why are they mutable? Why aren't they `const`? – Eljay Jun 20 '22 at 17:47
  • [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/) – Remy Lebeau Jun 20 '22 at 17:55
  • Strange `operator+` implementation... (but maybe that's beside the point). – Paul Sanders Jun 20 '22 at 20:02

2 Answers2

2

I think 2 can be converted to a MyClass object as the constructor of MyClass is not explicit.

The problem is that after the conversion from int to MyClass we will have a prvalue of type MyClass which cannot be bound to an lvalue reference to non-const MyClass.

Basically, an lvalue reference to nonconst type cannot be bound to an rvalue. But an lvalue reference to a const type can be bound to an rvalue. For example,

int &ref = 4; //not valid
const int &r = 4; //valid

To solve this, you can add a low-level const to the parameters as shown below:

//----------------------------------------- vvvvv----------------------->low level const added
MyClass operator +(const MyClass& lOperand, const MyClass& rOperand) {
    return lOperand;
}

Working demo

Jason
  • 36,170
  • 5
  • 26
  • 60
2

When you write

MyClass operator +(MyClass& lOperand, MyClass& rOperand)

you are signaling that you are modifying the 2 arguments, because otherwise you surely would have used const, right?

But if the integer literal 2 is converted to MyClass you have a temporary object that will be destroyed at the end of the function call. Any modifications made to it will be lost.

Surely if you are going to modify arguments then you want those modifications to persist. So C++ in all its wisdom has decreed that a prvalue, which you get from the conversion from int to MyClass, can not be bound to an *lvalue reference to non-const MyClass. That way you don't loose your precious modifications.

But really operator + should not be modifying it's arguments, declare them as const and all will be well.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42