Question

When I try compiling following program, I get an error on l-value which makes sense. Error is: error C2106: '=' : left operand must be l-value

Code:

int main() 
{
    int a,b,c,d;
    b+c=d;
    return 0;
 }

But following code works absolutely fine when I replace integer with my own structure

struct MyStruct
{
    int val;
    MyStruct(){}
};

MyStruct operator+(MyStruct& s1, MyStruct& s2)
{
    MyStruct temp;
    return temp;
}

int main() 
{

    MyStruct a,b,c,d;
    b+c=d;
    return 0;
}

How come the second code compiles? I know I can return const from the operator+. But isn't b+c in second example a rvalue? So how come it compiles

Was it helpful?

Solution

Cory Klein has already explained here why the code compiles.

I just want to add that if you want MyStruct to behave as the ints (and othe built-in types), then add this line to MyStruct:

MyStruct& operator =(const MyStruct&) && = delete;

This tells the compiler that that everytime the operator =() is called on a MyStruct object that is an rvalue (thanks to the ref-qualifier &&) the code should not be valid because the operator =() does not exist (= delete;). Indeed, GCC 4.8.1 emmits the following:

error: use of deleted function 'MyStruct& MyStruct::operator=(const MyStruct&) &&'

b+c=d;
   ^

Update: Following the comment by Casey (many thanks).

There's one issue with adding the line above to MyStruct. It also prevents assignment to an lvalue. That is, the line below also becomes illegal:

b = c;

If you want to disable assignment to an rvalue but still allows assignment to lvalues, then instead of the line above, add this one to MyStruct:

MyStruct& operator =(const MyStruct&) & = default;

(or provide a correct implementation if the compiler generated one doesn't fit your purposes.)

OTHER TIPS

In this code:

MyStruct a,b,c,d;
b+c=d;

As you have defined the operator+() function, it returns a MyStruct. Therefore b+c, which calls the function you defined, returns a MyStruct, and then the operator=() function is called on that MyStruct, and it is passed d as an argument.

Although the temporary MyStruct is an rvalue because of its temporary nature, the code still compiles because of the reasons I explained above, and the fact that the C++ standard does not forbid calling the operator=() function on an rvalue when that rvalue is a user defined object and not an integral type.

In this code:

int a,b,c,d;
b+c=d;

b+c returns an r-value int. Having an r-value on the left side of an = operator is not C++ syntax. Either way, it wouldn't make any sense to assign a value to it, whereas calling the operator=() function on a temporary MyStruct could potentially have side effects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top