右值作为函数参数的场景
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
void func(T& param)
{
cout << "传入的是左值" << endl;
}
template<typename T>
void func(T&& param)
{
cout << "传入的是右值" << endl;
}
template<typename T>
void warp(T&& param)
{
func(param);
}
int main()
{
int num = 2019;
warp(num);
warp(2019);
return 0;
}
这段代码输出的结果是左值、左值。
在main函数中分别向warp函数传递了一个左值和右值,参数匹配没有问题,但是因为形参具有名字从而使传进去的右值变为了左值,导致参数再进行传递时匹配到了左值的func。
完美转发
那么如何让形参能正确的匹配到右值参数呢?
查看warp的参数匹配结果,分别匹配成了int #
和int##
。也就是说,模板中的 T 保存着传递进来的实参的信息,我们可以利用 T 的信息来强制类型转换我们的 param 使它和实参的类型一致。
如果我们可以将其强制转换回右值,就能匹配到右值的函数啦。类似这样
template<typename T>
T&& forward(T ¶m)
{
return static_cast<T&&>(param);
}
这样当传入的值是右值时,可以返回右值,当传入值是左值时会返回左值,这样就实现了完美转发。
这里涉及到引用折叠,后面会更详细的学习引用折叠
的问题。
代码如下;
template<typename T>
void warp(T&& param)
{
func(std::forward<T>(param));
}