深入理解C++11(十四)

深入理解C++11(十四)

forward和完美转发
右值引用类型是独立于值的,一个右值引用参数作为函数的形参,在函数内部再转发该参数的时候它已经变成一个左值了,并不是它原来的类型了。比如:

template <typename T>
void forwardValue(T& val)
{
processValue(val); // 右值参数会变成左值
}
template <typename T>
void forwardValue(const T& val)
{
processValue(val); // 参数都变成常量左值引用了
}

都不能按照参数的本来的类型进行转发

因此,我们需要一种方法能按照参数原来的类型转发到另一个函数,这种转发被称为完美转发。所谓完美转发(Perfect Forwarding),是指在函数模板中,完全依照模板的参数的类型(即保持参数的左值、右值特征),将参数传递给函数模板中调用的另外一个函数。C++11中提供了这样的一个函数std::forward,它是为转发而生的,不管参数是T&&这种未定的引用还是明确的左值引用或者右值引用,它会按照参数本来的类型转发。看看这个例子:

template<typename T>
void PrintT(T& t)
{
cout <<"lvaue"<< endl;
}
template<typename T>
void PrintT(T && t)
{
cout <<"rvalue"<< endl;
}
template<typename T>
void TestForward(T && v)
{
PrintT(v);
PrintT(std::forward<T>(v));
PrintT(std::move(v));
}
Test()
{
TestForward(1);
int x = 1;
TestForward(x);
TestForward(std::forward<int>(x));
}

测试结果如下图:
在这里插入图片描述
我们来分析一下测试结果:

·TestForward(1):由于1是右值,所以未定的引用类型T&&v被一个右
值初始化后变成了一个右值引用,但是在TestForward函数体内部,调用
PrintT(v)时,v又变成了一个左值(因为在这里它已经变成了一个具名的变
量,所以它是一个左值),因此,第一个PrintT被调用,打印出“lvaue”。调
用PrintT(std::forward(v))时,由于std::forward会按参数原来的类型
转发,因此,它还是一个右值(这里已经发生了类型推导,所以这里的T&&
不是一个未定的引用类型(关于这点可以参考2.1节),会调用void
PrintT(T&&t)函数。调用PrintT(std::move(v))是将v变成一个右值
(v本身也是右值),因此,它将输出rvalue。

·TestForward(x)未定的引用类型T&&v被一个左值初始化后变成了一
个左值引用,因此,在调用PrintT(std::forward(v))时它会被转发到
void PrintT(T&t)。

右值引用、完美转发再结合可变模板参数,我们可以写一个万能的函数包装器(可变模板参数将在3.2节中介绍,读者不妨读完下一节再回头来看这个函数),带返回值的、不带返回值的、带参数的和不带参数的函数都可以委托这个万能的函数包装器执行。下面看看这个万能的函数包装器。

template<class Function, class... Args>
inline auto FuncWrapper(Function && f, Args && ... args) -> decltype(f(std::for
ward<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;
}
test()
{
FuncWrapper(test0); // 没有返回值,打印
1
FuncWrapper(test1); // 返回
1
FuncWrapper(test2, 1); // 返回
1
FuncWrapper(test3, "aa", "bb"); // 返回
"aabb"
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值