003-EMC 深入解讀-理解模板型別推導(三)
阿新 • • 發佈:2018-12-12
上一篇文章我們介紹了 ParamType 是引用或指標的情況,這一節繼續第二條規則,也是最複雜的規則。
ParamType 是引用或指標,但不是通用引用- ParamType 是通用引用
- ParamType 既非指標也非引用
1. ParamType 是通用引用
首先你得明白,何為通用引用(Universal Reference). 下面是一個比較平易近人的定義:
"函式模板中持有型別形參 T
時,Universal Reference 型別寫作 T&&
"
注意:不要將通用引用與左值引用相混淆,雖然看上去長的很像。
例如:
// T&& 稱為通用引用
template< typename T>
void f(T&& param);
那麼通用引用的推導規則是怎樣的?
針對於 f(expr)
呼叫:
- 如果 expr 是左值,T 會被推導成一個引用(同時保留型別修飾詞,比如 const),T&& 也會被推導成引用。(這很奇怪,後面會解釋。)
- 如果 expr 是右值,對 expr 的型別與 T 執行模式匹配,決定 T 的型別。(這也很抽象,後面看例子。)
下面來看示例:
- 例
template<typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
// x 是左值,T 是 int&, T&& = int&&& = int&
f(x);
// cx 是左值,T 是 const int&, T&& = const int&&& = const int&
f(cx);
// rx 是左值,T 是 const int&, T&& = const int&&& = const int&
f(rx);
// 27 是右值,T 是 int, T&& = int&&
f(27);
比較奇怪的是,當 T 被推導為一個引用時,T&& 也被推導為一個引用,就像:
T = int&
T&& = int&&& = int&
這種變換是什麼鬼?到這裡,編譯器會一聲不坑的幫你把 int&&&
處理成 int&
,這背後實際上是一種被稱為“引用摺疊”的東西在搞鬼。你暫時可以理解為下面這幾種情況:
T& + & = T&
T&& + & = T&
T& + && = T&
T&& + && = T&&
不過後面,到了 item28 的時候,還會詳細描述。
2. 實驗
在這個系列的文章中,我準備了大量的程式碼來驗證我們的想法。您可以拉取所有程式碼進行閱讀,歡迎隨時留言提問。
本節的程式碼路徑:emc/item01/demo04.cpp
3. 總結
- 理解通用引用時的推導規則