dreamer
dreamer

Reputation: 171

Why is int foo() an rvalue, while int& foo() is an lvalue in this example?

We have the following code example:

// lvalues:
  //
  int i = 42;
  i = 43; // ok, i is an lvalue
  int* p = &i; // ok, i is an lvalue
  int& foo();
  foo() = 42; // ok, foo() is an lvalue
  int* p1 = &foo(); // ok, foo() is an lvalue

// rvalues:
  //
  int foobar();
  int j = 0;
  j = foobar(); // ok, foobar() is an rvalue
  int* p2 = &foobar(); // error, cannot take the address of an rvalue
  j = 42; // ok, 42 is an rvalue

I'm trying to understand why does a plain function definition as this:

int foobar();

is supposed to be an rvalue, while the same function but with an object reference as the return type, as this:

int& foobar();

is an lvalue. (The second part somehow comes naturally, because we specifically ask for and thus keep a reference when defining the function. However, the first example is hard to grasp for me, as I was expecting that the memory location of a function is somehow implicitly deducted, based on the assumption -that might be wrong-, that each function has its own, non changeable location in memory and, in conclusion, the first example should have also been an lvalue reference). Please try and explain this aspect, first.

I understand that:

An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the & operator. An rvalue is an expression that is not an lvalue.

However, as stated above, I'm mostly interested in how functions, as opposed to or in correlation to simple objects, are treated regarding the lvalue/rvalue concept.

Thank you!

Upvotes: 0

Views: 280

Answers (1)

bolov
bolov

Reputation: 75698

foobar() is not a function. It's a function call. The evaluation of it is the result of calling the function, i.e. an int which is an rvalue.

Here is how you would assign the function to a reference (which is a better test than taking its address):

int (&a)() = foo; // OK
int (&&b)() = foo; // OK

This is how you would assign the function address

int (*a)() = &foo; // OK

I understand that: "An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the & operator. An rvalue is an expression that is not an lvalue."

Well... that's a pretty simplistic definition. Here are some links if you are interested in the subject:

What are rvalues, lvalues, xvalues, glvalues, and prvalues?

Value categories

Upvotes: 4

Related Questions