Home > Software engineering >  lvalue reference on rvalue reference
lvalue reference on rvalue reference

Time:08-17

I have an interesting example to understand lvalue reference, rvalue reference, and std::forward. Maybe it will be a useful example for a deep understating concept.

void foo(int&& a){
  cout<<"foo&&"<<endl;
}

void foo(int& a){
  cout<<"foo&"<<endl;
}

template <typename T>
void wrapper(T&& a){
  cout<<"wrapperTemplate"<<endl;
  foo(forward<T>(a));
};

int main()
{
  double&& a=5;
  double& t=a;
  wrapper(t);
}

The output is:

wrapperTemplate
foo&&

CodePudding user response:

You can't call the lvalue reference version, as t is a double and foo() expects an int. And you can't bind the temporary generated by the implict cast from double to int to an lvalue reference. The temporary is an rvalue, so can be used to call the rvalue overload.

The fact that a is an rvalue reference doesn't change the result:

double a=5;
double& t=a;
wrapper(t);

still prints:

wrapperTemplate
foo&&

https://godbolt.org/z/89T7Wzc8e

If the types do match, the lvalue reference function is called:

int a=5;
int& t=a;
wrapper(t);

prints:

wrapperTemplate
foo&

https://godbolt.org/z/chnzaKhGf

If you use std::move(), you get back to the rvalue reference version:

int a=5;
int& t=a;
wrapper(std::move(t));

prints:

wrapperTemplate
foo&&

https://godbolt.org/z/68KPYrhYP

Removing wrapper also doesn't change the behaviour:

double a=5;
foo(a);
int b=5;
foo(b);
foo(std::move(b));

prints:

foo&&
foo&
foo&&

https://godbolt.org/z/fds6sKvhW

  • Related