简体   繁体   中英

lvalue reference on rvalue reference

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&&

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

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