Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalue and lvalue reference with lambda expressions - gcc vs. msvc

In C++, it is illegal to implicitly convert an rvalue to an lvalue reference. Consider the following code where an lvalue reference is bound to an rvalue (the lambda):

int main()
{
    auto& f = []() -> void {};
    return 0;
}

gcc (4.8.1) does not accept such code (makes perfect sense). However, Microsoft compiler does accept it meaning that either it is accepting nonstandard code or C++ allows the particular case where an lvalue reference is bound to an rvalue lambda expression.

The question: which assumption is correct?

like image 411
a.lasram Avatar asked Jun 15 '13 20:06

a.lasram


People also ask

What is the difference between L value and R value references?

“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. References in C++ are nothing but the alternative to the already existing variable. They are declared using the '&' before the name of the variable.

What is rvalue in C ++ 11?

lvalue : A value that resides in memory (heap or stack) and addressable. rvalue : A value that's not lvalue. It resides only on the right side of an assignment expression such as a literal or a temporary which is intended to be non-modifiable.

What is L value and R value in C++?

An lvalue (locator value) represents an object that occupies some identifiable location in memory (i.e. has an address). rvalues are defined by exclusion. Every expression is either an lvalue or an rvalue, so, an rvalue is an expression that does not represent an object occupying some identifiable location in memory.

What is the purpose of an rvalue reference?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.


3 Answers

The core of your question is: can rvalues be bound to non-const lvalue references?

The Standard says no. rvalues can only be bound to const lvalue references.

I believe the relevant Standard paragraph is 8.5.3/5:

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

...

  • Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.

However Microsoft has a long-standing "feature" that allows this non-standard behaviour, which explains what you're witnessing.

like image 195
syam Avatar answered Nov 16 '22 20:11

syam


However, Microsoft compiler does accept it meaning that either it is accepting nonstandard code or C++ allows the particular case where an lvalue reference is bound to an rvalue lambda expression.

MSVC is known for having this (not so great) compiler extension. It simply allows binding rvalues to lvalue references to non-const:

A& x = A(); // Illegal in C++, allowed by MSVC
like image 21
Andy Prowl Avatar answered Nov 16 '22 20:11

Andy Prowl


To quote Herb Sutter (chair of the ISO C++ standards committee):

A conforming C++ compiler can always allow otherwise-illegal C++ code to compile and give it some meaning — hey, it could choose to allow inline COBOL if some kooky compiler writer was willing to implement that extension, maybe after a few too many Tequilas. For some kinds of extensions the C++ standard requires that the compiler at least emit some diagnostic to say that the code isn’t valid ISO C++, as this compiler does.

He explains further how the following example is illegal:

// Example 2

string f() { return "abc"; }

void g() {
string& s = f();       // illegal?
  cout << s << endl;
}

Please visit this link by Sutter for an explanation, to avoid duplicating the article on SO.

like image 3
user1055604 Avatar answered Nov 16 '22 18:11

user1055604