C++11学习笔记:std::move和std::forward源码分析(二)

2015-01-27 06:07:57 · 作者: · 浏览: 11
rward函数在将参数右值 X() 转发给了inner函数时,成功地保留了参数 X() 的右值属性。首先我们来分析 outer(a) 这种调用forward函数转发左值参数的情况。模拟单步调用来到测试代码第8行,T&& <=> X&, t <=> a 。
根据函数模板参数推导规则,T&& <=> X& 可推出 T <=> X& 。
forward (t) <=> forward (t),其中 t 为指向 a 的左值引用。
再次单步调用进入forward函数实体所在的源码第4行或第9行。
先尝试匹配源码第4行的forward函数,_Tp <=> X& 。typename std::remove_reference<_Tp>::type <=> X 。
typename std::remove_reference<_Tp>::type& <=> X& 。形参 __t 与实参 t 类型相同,因此函数匹配成功。再尝试匹配源码第9行的forward函数,_Tp <=> X& 。typename std::remove_reference<_Tp>::type <=> X 。
typename std::remove_reference<_Tp>::type&& <=> X&& 。形参 __t 与实参 t 类型不同,因此函数匹配失败。由10与13可知7单步调用实际进入的是源码第4行的forward函数。static_cast<_Tp&&>(__t) <=> static_cast (t) <=> a。inner(forward (t)) <=> inner(static_cast (t)) <=> inner(a) 。outer(a) <=> inner(forward (t)) <=> inner(a)
再次单步调用将进入测试代码第5行的inner(const X&) 版本,左值参数转发成功。然后我们来分析 outer(X()) 这种调用forward函数转发右值参数的情况。模拟单步调用来到测试代码第8行,T&& <=> X&&, t <=> X() 。根据函数模板参数推导规则,T&& <=> X&& 可推出 T <=> X 。
forward (t) <=> forward (t),其中 t 为指向 X() 的右值引用。
再次单步调用进入forward函数实体所在的源码第4行或第9行。先尝试匹配源码第4行的forward函数,_Tp <=> X 。typename std::remove_reference<_Tp>::type <=> X 。
typename std::remove_reference<_Tp>::type& <=> X& 。形参 __t 与实参 t 类型相同,因此函数匹配成功。再尝试匹配源码第9行的forward函数,_Tp <=> X 。typename std::remove_reference<_Tp>::type <=> X 。
typename std::remove_reference<_Tp>::type&& <=> X&& 。形参 __t 与实参 t 类型不同,因此函数匹配失败。由25与28可知22单步调用实际进入的仍然是源码第4行的forward函数。
static_cast<_Tp&&>(__t) <=> static_cast (t) <=> X()。inner(forward (t)) <=> inner(static_cast (t)) <=> inner(X())。outer(X()) <=> inner(forward (t)) <=> inner(X())
再次单步调用将进入测试代码第6行的inner(X&&) 版本,右值参数转发成功。
由17和32可知源码中std::forward函数的具体实现符合标准,
因为无论用左值a还是右值X()做参数来调用带有右值引用参数的函数模板outer,
只要在outer函数内使用std::forward函数转发参数,
就能保留参数的左右值属性,从而实现了函数模板参数的完美转发。