std::forward
void funcLast2(int&& v1, int& v2) //v1是右值 { cout << v1 << endl; cout << v2 << endl; } template<typename F, typename T1,typename T2> void funcMiddle_Temp(F f, T1&& t1, T2&& t2) { f(t1, t2); }
- 调用
int j = 70; funcLast2(20, j); //20,70 funcMiddle_Temp(funcLast2, 20, j);
- 编译报错,原因:20传递到t1(int &&),t1(本身是左值)传递给v1(右值)。
解决方法:使用std::forward
template<typename F, typename T1,typename T2> void funcMiddle_Temp(F f, T1&& t1, T2&& t2) { //f(t1, t2); f( std::forward<T1>(t1), //T1 = int std::forward<T2>(t2) //T2 = int & ); }
- std::forward 是C++11中专门为转发而存在的函数。这个函数要么返回一个左值,要么返回一个右值。
- 万能引用类型才是forward能够发挥作用的重要条件。
- 理解:
- (a)实参原来是个左值j,到了形参中还是左值t2。forward能够转化回原来该实参的左值或者右值性。所以,forward之后还是个左值。
- (b)实参原来是个右值20,到了形参中变成了左值t1。forward能够转化回原来该实参的左值或者右值性。所以,forward之后还是个右值。
- forward这个函数有强制把左值转换成右值的能力。所以:forward这个函数只对原来是个右值这种情况有用。
- forward的能力:保持原始实参的左值性或者右值性。
void printInfo(int& t) { cout << "printInfo()参数类型为左值引用" << endl; } void printInfo(int&& t) { cout << "printInfo()参数类型为右值引用" << endl; } void printInfo(const int& t) { cout << "printInfo()参数类型为const 左值引用" << endl; } template <typename T> void TestF(T&& t) { printInfo(std::forward<T>(t)); }
- 调用
TestF(1); //printInfo()参数类型为右值引用 int i = 5; TestF(i); //printInfo()参数类型为左值引用 TestF(std::move(i)); //printInfo()参数类型为右值引用 ----std::move能够将左值转换成右值 const int j = 8; TestF(j); //printInfo()参数类型为const 左值引用 ------j是个const左值 TestF(int(12)); //printInfo()参数类型为右值引用 ----int(12)是个临时对象,是个右值。 int&& tempvalue = 16; TestF(tempvalue);//printInfo()参数类型为左值引用
- 输出
完美转发理解:结合万能引用,即使在传入的参数经过中间函数操作后其类型发生改变的情况下,也能回归最初的实参本来的类型。
普通参数的完美转发
- 【注意】:auto &&是万能引用。
int getData() { return 3; } void funcLast3(int v1) { cout << "v1=" << v1 << endl; } void funcMiddle_Temp2() { auto&& result = getData(); //getData返回的是右值,所以auto = int ,result = int &&(右值引用) //....对result做各种运算。 funcLast3( std::forward<decltype(result)>(result) ); }