您的位置:首页 > 其它

引用折叠和完美转发

2016-03-10 14:12 323 查看
如下来分析使用右值引用 + 新增的引用折叠推导规则,如何来达成完美转发

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

其中 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 右值
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: