1. 程式人生 > >003-EMC 深入解讀-理解模板型別推導(三)

003-EMC 深入解讀-理解模板型別推導(三)

上一篇文章我們介紹了 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. 總結

  • 理解通用引用時的推導規則