简介
一个右值引用参数作为函数的形参,在函数内部再转发该参数的时候它已经变成一个左值了,并不是原来的类型。
比如:
template <typename T>
void forwardValue(T &&val)
{
processValue(val); // 右值引用参数会变成左值
}
如果我们需要按照参数原来的类型转发到另一个函数,这种转发就被成为完美转发。
所谓完美转发,是指在函数模板中,完全依照模板的参数的类型(即保持参数的左值、右值特征),将参数传递给函数模板中调用的另一个函数。
C++11提供了一个函数用于解决这个问题,通过std::forward
来实现,不管参数是T&&这种未定的引用还是明确的左值引用或者右值引用,它会按照参数原本的类型转发。
示例
using namespace std;
template<typename T>
void PrintT(int &t)
{
cout << "lvalue" << endl;
}
template<typename T>
void PrintT(int &&t)
{
cout << "rvalue" << endl;
}
template<typename T>
void TestForward(T && v)
{
PrintT(v);
PrintT(std::forward<int>(v));
PrintT(std::move(v));
cout << endl;
}
int main()
{
TestForward(1);
int x = 1;
TestForward(x);
TestForward(std::forward<int>(x));
test();
return 0;
}
结果:
lvalue
rvalue
rvalue
lvalue
rvalue
rvalue
lvalue
rvalue
rvalue
注意第三个示例测试代码:
TestForward(std::forward<int>(x));
经过std::forward<int>(x)
后变成了右值。
forward的转换规则为:
- 模板参数为引用类型T、T&&时,返回右值引用
- 模板参数为引用类型T&时,返回左值引用
扩展
右值引用、完美转发再结合可变模板参数,可以写一个万能的函数包装器,带返回值的、不带返回值的、带参数的或者不带参数的都可以委托这个万能的函数包装器来实现参数的完美转发。
万能函数包装器:
template<typename Function,typename... Args>
inline auto FuncWrapper(Function && f,Args && ... args) -> decltype (f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
测试:
void test0()
{
cout << "void" << endl;
}
int test1()
{
return 1;
}
int test2(int x)
{
return x;
}
string test3(string s1,string s2)
{
return s1+s2;
}
void test()
{
FuncWrapper(test0);
cout << FuncWrapper(test1) << endl;
int a = 1;
cout << FuncWrapper(test2,a) << endl;
cout << FuncWrapper(test3,"aa","bb") << endl;
}
输出:
void
1
1
aabb
参考:《深入应用C++11》
https://blog.csdn.net/u012508160/article/details/79218936