完美轉發實現了參數在傳遞過程中保持其值類別的功能,即,若是左值,則傳遞之後仍然是左值,若是右值,則傳遞之後仍然是右值。
forawrd
的函數聲明爲:
template< class T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;
std::remove_reference<T>
其定義爲:
template< class T > struct remove_reference {typedef T type;}; template< class T > struct remove_reference<T&> {typedef T type;}; template< class T > struct remove_reference<T&&> {typedef T type;};
其作用便是去除類型模板形參中的引用。如:
remove_reference<int>::type => int remove_reference<int&>::type => int remove_reference<int&&>::type => int
引用摺疊規則
右值引用的右值引用會摺疊爲右值引用,其他情況下,全部摺疊爲左值引用。
typedef int& lref; typedef int&& rref; int n; lref& r1 = n; // type of r1 is int& lref&& r2 = n; // type of r2 is int& rref& r3 = n; // type of r3 is int& rref&& r4 = 1; // type of r4 is int&&
分析
設 T 的實際類型(經推斷/顯式指定)爲 A,以下以 int 類型爲例。
如果 A 爲 int
,則 forward 的返回值類型爲 int&&
。
如果 A 爲 int&
,則 forward 的返回值類型爲 int& &&
,經引用摺疊之後,返回值類型爲 int&
;
如果 A 爲 int&&
,則 forward 的返回值類型爲 int&& &&
,經引用摺疊之後,返回值類型爲 int&&
。
…
此外,模板實參推斷規則中有一條爲:如果形參是一個非 const/volatile 修飾的右值引用,且函數調用時傳遞的實參是一個左值,設其類型爲 int,那麼 A 便爲 int&
。
例子:
template<class T>
void wrapper(T&& arg) {
foo(std::forward<T>(arg));
}
int i = 1;
wrapper(i); // T = int&,std::forward<T>(arg) 返回值類型爲 int&
wrapper(1); // T = int,std::forward<T>(arg) 返回值類型爲 int&&
const ci = 1;
wrapper(ci); // T = const int&,std::forward<T>(arg) 返回值類型爲 const int&