引用折叠和完美转发

如下来分析使用右值引用 + 新增的引用折叠推导规则,如何来达成完美转发


进行转发的函数模板定义如下

其中 WrapFunc 函数模板将参数转发给 InnerFunc 函数

template<class A>
void WrapFunc(A &&a)
{
InnerFunc(static_cast<A &&>(a)); 
}



先给出转发结果,后面分析原因

转发结果

non-const左值  --->  non-const左值
const左值        --->    const左值
non-const右值  --->  non-const右值
const右值  --->  const右值


疑问点1:函数模板的函数形参为右值引用形式,他能正确的转发左值吗?

函数模板的函数形参为右值引用形式,并不是说该函数模板实例的函数形参为右值引用

我们使用的是函数模板实例化后的模板函数,而不是该函数模板

因此,要看进行了进行实参推演后得到的函数模板实例的函数形参类型,才能决定他能接受什么值类型的参数



引用折叠

由疑问点1,我们知道,要判断该函数模板是否能完美转,要看在使用该函数模板进行实参推演时

推演得到的模板函数的函数形参是什么。因此是否能正确的推演出合理的类型,是该函数模板是否

能完美转发的关键,而引用折叠正是C++11新增的,在进行实参推演时使用的一个规则



设 T 为模板形参,A 为一个已经定义的类型

如下分析引用折叠的规则


若函数模板的函数形参为 T&
若 T 被推演成 A,函数形参 A& 无需引用折叠,得到目标类型为 A&
若 T 被推演成 A&,函数形参 A& & 进行引用折叠后,得到目标类型为 A&
若 T 被推演成 A&&,函数形参 A&& &进行引用折叠后,得到目标类型为 A&


若函数模板的函数形参为 T&&
若 T 被推演成 A,函数形参 A&& 无需引用折叠,得到目标类型为 A&&
若 T 被推演成 A&,函数形参 A& && 进行引用折叠后,得到目标类型为 A&
若 T 被推演成 A&&,函数形参 A&& && 进行引用折叠后,得到目标类型为 A&&





完美转发的原因分析


若实参为 A类型的 non-const左值
匹配类型:A&
根据实参推演规则,函数模板的函数形参为 非 cv 限定的右值引用形式,且实参为左值
则匹配类型为实参类型的引用类型,因此匹配类型为 A&
参数化类型:T
根据实参推演规则,函数模板的函数形参为引用形式,则参数化类型为 T
目标类型:A&
实参推演后,T 被推演成 A&
目标类型为 A& &&,进行引用折叠后为 A&
转发效果
转发给 InnerFunc 的是 形参 A &a,还是 non-const 左值




若实参为 A类型的 const左值
匹配类型:const A&
根据实参推演规则,函数模板的函数形参为 非 cv 限定的右值引用形式,且实参为左值
则匹配类型为实参类型的引用类型 且 保留 cv 限定符,因此匹配类型为 const A&
参数化类型:T
根据实参推演规则,函数模板的函数形参为引用形式,则参数化类型为 T
目标类型:const A&
实参推演后,T 被推演成 const A&
目标类型为 const A& &&,进行引用折叠后为 const A&
转发效果
转发给 InnerFunc 的是 形参 const A&,还是 const 左值




若实参为 A类型的 non-const 右值
匹配类型:A
虽然函数形参为右值引用,但实参为右值,因此匹配类型就是该实参的类型,即为 A
参数化类型:T
根据实参推演规则,函数模板的函数形参为引用形式,则参数化类型为 T
目标类型:A&&
实参推演时,由于实参为 A类型的右值,被推演成 A&&
目标类型为 A&& &&,进行引用折叠后为 A&&
转发效果
具名的右值引用形参 A &&a 为左值,但经过 static_cast<A &&> 转换后变成了右值
因此转发给 InnerFunc 的,还是 non-const 右值




若实参为 A类型的 const 右值
匹配类型:const A
函数形参为引用形式,因此匹配类型为保留 cv 限定符
虽然函数形参为右值引用,但实参为右值,因此匹配类型就是该实参的类型,即为 const A
参数化类型:T
根据实参推演规则,函数模板的函数形参为引用形式,则参数化类型为 T
目标类型:const A&&
实参推演时,由于实参为 const A类型的右值,被推演成 const A&&
目标类型为 const A&& &&,进行引用折叠后为 const A&&
转发效果
具名的右值引用形参 const A&&a 为const左值,但经过 static_cast<const A&&> 转换后变成了const右值
因此转发给 InnerFunc 的,还是 const 右值





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值