Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understading this perfect forwarding example

I came across the following example while attempting to understand what std::forward does

// forward example
#include <utility>      // std::forward
#include <iostream>     // std::cout

// function with lvalue and rvalue reference overloads:
void overloaded (const int& x) {std::cout << "[lvalue]";}
void overloaded (int&& x) {std::cout << "[rvalue]";}

// function template taking rvalue reference to deduced type:
template <class T> void fn (T&& x) {
  overloaded (x);                   // always an lvalue
  overloaded (std::forward<T>(x));  // rvalue if argument is rvalue
}

int main () {

  std::cout << "calling fn with rvalue: ";
  fn (0);
  std::cout << '\n';

  return 0;
}

The output of the program is

calling fn with rvalue: [lvalue][rvalue]

Now my question is how did we get lvalue first ? Here is my line of thought in our main I called fn(0); Now 0 is rvalue. So the universal reference x is deduced to the following

void fn (int&& && x);

Now according to reference collapsing we would get

void fn (int&& x);

Thus making x behave like an rvalue.So if x is passed then rvalue overloaded method should be called. However it seems the other overloaded lvalue reference function is called. I would appreciate it if someone could clarify this

like image 880
MistyD Avatar asked Oct 20 '22 08:10

MistyD


1 Answers

A named variable is NEVER an rvalue. It is invariably an lvalue. Rvalues are only pure expressions which don't have names.

int && i = int(0);

Here the expression int(0) is an rvalue, but the variable i itself is an lvalue, declared to be binding to an rvalue.

like image 51
Nawaz Avatar answered Oct 26 '22 22:10

Nawaz