001 EMC 深入解讀 理解模板型別推導(一)

2021-08-28 04:01:54 字數 2792 閱讀 3701

emc 第一章條款一,一上來就出個王炸——有關於函式模板的推導規則。

似乎你在使用的時候並未關注過這些事情,因為一切看起來相當自然,你也用的很爽。比如:

template t>

t add(t a, t b)

這是乙個計算兩數之和的函式,你可以傳遞 float, double, int 等支援 operator+ 型別的引數,而不用為每一種型別都寫乙份 add 函式。

但是,上面的函式模板你也可以寫成:

template t>

t add(t& a, t& b)

template t>

t add(const t& a, const t& b)

template t>

t add(t&& a, t&& b)

然而,上面這 3 種寫法在 c++11 中都好使。到底哪種比較好?或者說,有什麼區別?從直覺上來說,寫在 add(t a, t b) 是值傳遞,而帶 & 的則是引用傳遞,帶 const 則表示希望物件保持常量屬性。你的直覺是對的。

那麼 t&& 是什麼?這是 c++11 出現的特有語法,你也許聽說過右值引用,很抱歉,看起來 t&& 確實像右值引用,不過,當 && 出現在模板引數 t 後面時,則稱為universal reference(通用引用、萬能引用)。接下來我們給乙個比較正式的定義:

函式模板中持有型別形參 t 時,universal reference 寫作 t&&
現在將問題抽象一下,對於下面的模板:

template

void f(paramtype param)

問題:在不同的模板引數裡,傳遞不同型別的引數,t 會被編譯器推導為什麼?paramtype 又是什麼?

例如:

template

void f(const t& param) // paramtype = const t&

int x = 27;

const

int cx = x;

const

int& rx = x;

當你呼叫f(x),f(cx),f(rx)時,t 是什麼,paramtype 是什麼?

事實上,上面的 3 種情況,t 全部被推導為int,所以,paramtype =const t&=const int&.

如果模板是:void f(t& param),情況又是怎樣呢?如何在你的編譯器中驗證?

我們沒乙個比較好的直接的方法在程式裡列印出推導的型別,但是可以利用鏈結器的錯誤提示來看到實際推導型別。

編譯以下**,命名為 deduce01.cpp

// deduce01.cpp

template

void f(t& param); // 故意不寫 f 的定義

int main()

使用下面方式編譯:

圖1 呼叫 f(x)

可以看到,f(x) 裡,t 被推導為 int,而 paramtype 被推導為 int &.

如果呼叫 f(cx),再進行編譯:

// deduce.01.cpp

template

void f(t& param); // 故意不寫 f 的定義

圖2 呼叫 f(cx)

可以看到,呼叫 f(cx) 時,t 被推導為 int const, paramtype 被推導為 int const&.

如果呼叫 f(rx),再進行編譯:

// deduce.01.cpp

template

void f(t& param); // 故意不寫 f 的定義

圖3 呼叫 f(rx)

推導的型別和呼叫 f(cx) 一模一樣。

同樣的,我們編譯 deduce02.cpp,使用上述方法編譯:

// deduce02.cpp

template

void f(const t& param); // 故意不寫 f 的定義

圖4 呼叫 f(x), f(cx), f(rx)

你發現,只報了乙個鏈結錯誤,這意味著這 3 次呼叫,推導的結果是一樣的。t 被推導為 int,而 paramtype 被推導為 int const&.

後文我們繼續討論具體的規則:

深入理解模板1

1,模版引數可以有三種型別 1 型別 2 編譯時常量 3 其他模版.2,型別 include include using namespace std template class stack int main 3,編譯時常量 include include using namespace std t...

深入理解讀寫鎖 ReadWriteLock原始碼分析

public inte ce readwritelockclass cacheddata downgrade by acquiring read lock before releasing write lock rwl.readlock lock finally try finally class ...

深入理解函式模板

函式模板深入理解 編譯器從函式模板通過具體型別產生不同的函式 編譯器會對函式模板進行兩次編譯 對模板 本身進行編譯 對引數替換後的 進行編譯 注意事項 函式模板本身不允許隱式型別轉換 自動推導型別時,必須嚴格匹配 顯示型別指定時,能夠進行隱式型別轉換 程式設計實驗 函式模板本質分析 include ...