简体   繁体   中英

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?

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 (ie, 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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM