std::forward在参数传递的过程中,我们总希望将参数的类型原原本本地传递下去,但现实确实很"残酷"的,往往将一个右值引用参数作为函数的形参,在函数内部再转发该参数的时候它已经变成一个左值,并不是他原来的类型。
因此,需要一种方法能够按照参数原来的类型转发到另一个函数,这种转发类型称为完美转发(Perfect Forwarding)。即是说完全依照模板的参数的类型(即保持参数的左值、右值特征)。
void func(int i){}; //#1
void func(int &&i){}; //#2
template<class T>
void funcWrap(T && param)
{
func(param); //#5
}
int main()
{
int x = 10;
funcWrap(x); //#3
funcWrap(10); //#4
func(10); //#6
}
1.这里#3和#4最终输出都会调用到#1,为什么?
因为在参数传递的过程中,都会退变为左值,所以在#5就只会调用到#1处。
2.#6的执行会不会有问题?
会,因为参数10是一个右值,经过重载决议后选不出最优的,所以这里就会报错。
这里参数传递的过程中,都会退变为左值,很明显不符合期望,稍加改造:
func(std::forward<T>(param)); //#5
思考:问什么这里的funcWrap要使用通用引用?
因为,要使用完美转发,势必是因为左值和右值都存在的情况,只有通用引用既能接受左值也能接收右值。完美转发与通用引用也是一对好拍档。
如果一个变量或者参数被声明为T&&,其中T是被推导的类型,那这个变量或者参数就是一个universal reference。