Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant as rvalue in C++(11)

Tags:

c++

gcc

c++11

Why const int is not an R-value in C++(11)? I thought that R-value was 'anything' which cannot be on the left hand side and constants fulfil that. This code fails:

int f(int && x) { return 100; }

void g() {
  const int x = 1;
  f(x);
}

error: invalid initialization of reference of type ‘int&&’ from expression
of type ‘const int’
like image 914
Cartesius00 Avatar asked Dec 05 '12 13:12

Cartesius00


People also ask

What is rvalue in C ++ 11?

Prerequisites: lvalue and rvalue in C++, References in C++ “l-value” refers to a memory location that identifies an object. “r-value” refers to the data value that is stored at some address in memory.

Can rvalue be const?

So an rvalue can be used both with rvalue overloads and a const lvalue reference.

What is lvalue vs rvalue?

An lvalue refers to an object that persists beyond a single expression. An rvalue is a temporary value that does not persist beyond the expression that uses it.


2 Answers

Ok, there are three categories of expressions1:

  1. those that represent objects that have an identity and cannot be moved from;
  2. those that represent objects that have an identity and can be moved from;
  3. those that represent objects that do not have an identity and can be moved from;

The first ones are called lvalues, the second ones are xvalues, and the third ones are prvalues. If we put lvalues and xvalues together, we have glvalues. Glvalues are all expressions that represent objects with an identity. If we put xvalues and prvalues together we have rvalues. Rvalues are all expressions that represent objects that can be moved.

The expression in question, x, is a glvalue: one can write &x, so the object clearly has an identity.

Can we move from this expression? Is this object about to expire? No, it is not. It only expires sometime after the current expression. That means it cannot be moved from. That makes it an lvalue.

All these names can be a bit confusing because lvalue and rvalue in C++ no longer mean what they meant in their C origins. The C++ meaning is completely unrelated to being on the left or right side of assignment2.

Personally, I prefer to use the terminology from this paper by Bjarne: iM-values (instead of lvalues), im-values (instead of xvalues), Im-values (instead of prvalues), i-values (instead of glvalues), and m-values (instead of rvalues). That is not the terminology that the standard uses, unfortunately.


1 Here "have an identity" means "its address can be taken"; "can be moved from" means that it is about to expire, either due to its temporary nature, or because the programmer made that explicit in the type system by calling std::move or something similar.

2 You can have rvalues on the left side of assignment: std::vector<int>(17) = std::vector<int>(42) is a valid expression, even if it is useless.

like image 192
R. Martinho Fernandes Avatar answered Oct 21 '22 08:10

R. Martinho Fernandes


I thought that R-value was 'anything' which cannot be on the left hand side [of an assignment operaton]

That's the C++03 definition of rvalue, and even then its a colloquialism and not universally true.

In C++11, the definitions for lvalue and rvalue have changed somewhat. The rules are complex, and individual situations are handled on a case-by-case basis in the Standard, but here is a general rule of thumb:

  1. If you can take the address of something, it is an lvalue
  2. If the type of an expression is an lvalue reference, that expression is an lvalue
  3. If neither of the above apply, it is an rvalue

In your particular case, you can take the address of x (eg, it "has a name") and it is therefore an lvalue.

You can read more about lvalues and rvalues in C++11 in two excellent articles:

  • rvalue References Explained, by Thomas Becker (blog article)
  • Universal References, by Scott Meyers (Overload #111)
like image 32
John Dibling Avatar answered Oct 21 '22 06:10

John Dibling