关于reference collapsing,可以看这个链接。(里面也讲了std::forward()和std::move()的实现)
http://thbecker.net/articles/rvalue_references/section_08.html
需要注意的是,在做auto-type deduction和template-type deduction的时候,在会有reference-stripping 发生:(来自scott meyers)
Note that when doing reference collapsing, reference would be stripped first:
Things get subtler when deducing the type for a variable that is itself a reference. In that case, the reference part of the type is ignored. For example, given
int x; ... int&& r1 = 10; // r1’s type is int&& int& r2 = x; // r2’s type is int&the type for both
r1
andr2
is considered to beint
in a call to the templatef
. This reference-stripping behavior is independent of the rule that, during type deduction for universal references, lvalues are deduced to be of typeT&
and rvalues of typeT
, so given these calls,f(r1); f(r2);the deduced type for both
r1
andr2
isint&
. Why? First the reference parts ofr1
’s andr2
’s types are stripped off (yieldingint
in both cases), then, because each is an lvalue, each is treated asint&
during type deduction for the universal reference parameter in the call tof
( from: "Nitty Gritty Detail" of https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers )
顺便附上std::move()和std::forward()的"伪"代码实现(from Scott Meyers):
1 //std::move() 2 template <typename T> 3 typename remove_reference<T>::type && 4 move(T&& param) 5 { 6 using ReturnType=typename remove_reference<T>::type &&; 7 return static_cast<ReturnType>(param); 8 } 9 //you can see that std::move() unconditionally cast anything to r-value
1 //std::forward() 2 template <typename T> 3 T&& forward(T&& param) 4 { 5 if(is_lvalue_reference<T>::value){ 6 return param; 7 } else { 8 return move(param); 9 } 10 } 11 //you can see that std::forward() perform conditional cast 12 //note that if we pass lvalue to a T&&, then it would collapse to lvalue-reference
:)