std::forward(expr)参数推导
2016-03-20 14:06
204 查看
对于forward,其boost的实现基本可以等价于这样的形式:
那么这里面是如何达到完美转发的呢?
举一个栗子
如上文所述,这里的i是一个左值,于是,我们在void foo(T&& fparam)这里的话,T将会被deduce成int& 然后Param Type为int&。(注意,我这里使用的变量名字为fparam,以便与forward的param进行区分)
那么为什么Param Type会是int&呢?因为按照正常的deduce,我们将会得到
先前我简单的提到了一句,C++不允许reference to reference,然而事实上,我们却会出现Lvalue reference to Rvalue reference[1], Lvalue reference to Lvalue reference[2], Rvalue reference to Lvalue reference[3], Rvalue reference to Rvalue reference[4]等四种情况,那么针对这样的情况,编译器将会根据引用折叠规则变为一个Single
Reference,那么是左值引用还是右值引用呢?其实这个规则很简单,只要有一个是左值引用,那么结果就是左值引用,其余的就是右值引用。于是我们知道了[1][2][3]的结果都是左值引用,只有[4]会是右值引用,而要从
这里T的Universal Reference让fparam拥有右值引用类型,那么则需要保证传递归来的参数为右值才可以,因为若是左值的话,T会deduce成左值引用,结合引用折叠规则,fparam的类型会是左值引用类型。
于是我们现在来看,int& &&这样的情况属于Lvalue reference to Rvalue reference,结果则为左值引用。那么,我们这个时候带入到forward函数来看看,首先是T变为了int&,经过了remove_reference变为了int,结合后面跟上的&,则变为了int&。然后我们再次替换 static_cast和return type的T为int&,都得到了int& &&
于是再应用引用折叠规则,int& &&都划归为了int&
于是,我们可以发现我们fparam变量的左值引用类型被保留了下来。这里也需要注意,我们到达forward的时候就已经是左值引用了,所以forward并没有改变什么。
如我们这时候是47这样的右值,我们知道了T会被deduce成int,经过了remove_reference,变为了int,跟上后面的&,成为了int&,然后再次替换static_cast和返回类型的T为int&&
于是,我们也可以发现,我们fparam变量的右值引用类型也完美的保留了下来。
更权威和详细的解释楼主可以阅读Effective Modern C++,那是本好书,我也只是把Meyers的观点简要的提炼了一下。
作者:蓝色
链接:https://www.zhihu.com/question/34544004/answer/59104471
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
template <typename T> T&& forward(typename remove_reference<T>::type& param) { return static_cast<T&&>(param); }
那么这里面是如何达到完美转发的呢?
举一个栗子
template<typename T> void foo(T&& fparam) { std::forward<T>(fparam); } int i = 7; foo(i); foo(47);
如上文所述,这里的i是一个左值,于是,我们在void foo(T&& fparam)这里的话,T将会被deduce成int& 然后Param Type为int&。(注意,我这里使用的变量名字为fparam,以便与forward的param进行区分)
那么为什么Param Type会是int&呢?因为按照正常的deduce,我们将会得到
void foo(int& &&fparam);
先前我简单的提到了一句,C++不允许reference to reference,然而事实上,我们却会出现Lvalue reference to Rvalue reference[1], Lvalue reference to Lvalue reference[2], Rvalue reference to Lvalue reference[3], Rvalue reference to Rvalue reference[4]等四种情况,那么针对这样的情况,编译器将会根据引用折叠规则变为一个Single
Reference,那么是左值引用还是右值引用呢?其实这个规则很简单,只要有一个是左值引用,那么结果就是左值引用,其余的就是右值引用。于是我们知道了[1][2][3]的结果都是左值引用,只有[4]会是右值引用,而要从
void foo(T&& fparam)
这里T的Universal Reference让fparam拥有右值引用类型,那么则需要保证传递归来的参数为右值才可以,因为若是左值的话,T会deduce成左值引用,结合引用折叠规则,fparam的类型会是左值引用类型。
于是我们现在来看,int& &&这样的情况属于Lvalue reference to Rvalue reference,结果则为左值引用。那么,我们这个时候带入到forward函数来看看,首先是T变为了int&,经过了remove_reference变为了int,结合后面跟上的&,则变为了int&。然后我们再次替换 static_cast和return type的T为int&,都得到了int& &&
int& && forward(int& param) { return static_cast<int& &&>(param); }
于是再应用引用折叠规则,int& &&都划归为了int&
int& forward(int& param) { return static_cast<int&>(param); }
于是,我们可以发现我们fparam变量的左值引用类型被保留了下来。这里也需要注意,我们到达forward的时候就已经是左值引用了,所以forward并没有改变什么。
如我们这时候是47这样的右值,我们知道了T会被deduce成int,经过了remove_reference,变为了int,跟上后面的&,成为了int&,然后再次替换static_cast和返回类型的T为int&&
int && forward(int& param) { return static_cast<int&&)(param); }
于是,我们也可以发现,我们fparam变量的右值引用类型也完美的保留了下来。
更权威和详细的解释楼主可以阅读Effective Modern C++,那是本好书,我也只是把Meyers的观点简要的提炼了一下。
作者:蓝色
链接:https://www.zhihu.com/question/34544004/answer/59104471
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章推荐
- Android_对象的创建And建造者模式
- 实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
- Myeclipse for Mac V2014 下载破解
- A^B所有因子和(poj1845 Sumdiv)
- 深入理解Java之泛型
- 终端命令
- Java程序员软件包
- Altium Designer 14.2.3 下载 安装 破解
- PAT Basic 1002. 写出这个数 (20)
- Effective Java2读书笔记-类和接口(二)
- windows环境下配置tornado
- 人工智能有简单的算法吗?Appendix: Is there a simple algorithm for intelligence?
- PB中的DataStore的应用示例
- 20145232 韩文浩 《Java程序设计》第3周学习总结
- 深度学习Deep learning
- Python 04 中并行遍历 zip,map,enumerate
- Java基础之八:数组
- 网红Papi酱获1200万融资
- Jenkins进阶系列之——06FTP publisher plugin插件下载(支持绝对路径)
- 为什么深度神经网络难以训练Why are deep neural networks hard to train?