怎么在建筑網(wǎng)站做翻譯兼職口碑營(yíng)銷的特點(diǎn)
在C++11及以上的相關(guān)語法中,特別是在模版元編程的范式里,類型推導(dǎo)是了重中之重。
在 《Effective Modern C++ 》 中第一章主要就是講各種類型推導(dǎo)。
當(dāng)然了,談到類型推導(dǎo),我們不得不先搞懂類型推導(dǎo)中的模式匹配,這是基礎(chǔ),本博客主要就是論述類型推導(dǎo)中的模式匹配。
隨后,本文將直接開始推倒 《Effective Modern C++》 中三大情況的各個(gè)例子,展現(xiàn)推導(dǎo)的具體思路
問題定義
函數(shù)模版大致形如:
template<typename T>
void f(ParamType param);//一次調(diào)用則形如:
f(expr);
在編譯期,編譯器會(huì)通過 expr
推導(dǎo)兩個(gè)型別,一個(gè)是 T
的型別,一個(gè)是 ParamType
的型別:
template<typename T>
void f(const T& param); //ParamType 是 const T&//調(diào)用語句如下:
int x = 0;
f(x) //以一個(gè) int 調(diào)用 f
我們可以依靠直覺就能得出正確答案: T
的型別是 int
,ParamType
的型別是 const int&
模式匹配的相關(guān)概念
在剛才,其實(shí)我們下意識(shí)得就使用了C++語法中的模式匹配:
首先需要明確的是,整個(gè)模式匹配行為就是:
對(duì) expr
對(duì)型別和 ParamType
的型別執(zhí)行模式匹配,來決定 T 的型別。
對(duì)于以下案例:
template<typename T>
void f(const T& param);int a = 27;
int* x = &a;
f(x);
匹配過程
根據(jù)模版類型推導(dǎo)的規(guī)則:
- 明確傳遞的參數(shù)
x
的類型是int*
。 - 函數(shù)參數(shù)的類型是
const T&
為了匹配 int*
和 const T&
,編譯器會(huì)去掉參數(shù)類型中的 const
和引用符號(hào)(為什么能夠去掉呢?在文末我會(huì)進(jìn)行解答),然后將剩余的部分與 T
進(jìn)行匹配:
- 參數(shù)的類型是
int*
,而函數(shù)參數(shù)的類型是const T&
- 去掉
const
和引用后,剩下的類型是int*
。
因此 T
被推導(dǎo)為 int*
;
最后我們把 T
套入 ParamType
,可知 ParamType
的類型是 const int*&
(同 int* const &),即指針的引用,并且還有一個(gè)底層 const
。
總結(jié)
一起來解答之前提出的相關(guān)問題吧:
- 「去掉參數(shù)類型中的
const
和引用符號(hào)」為什么能去掉他倆呢?請(qǐng)看下面對(duì)引用折疊的相關(guān)描述,其實(shí)為什么要去掉 const 也是一樣的邏輯,如果我們的 ParamType 中不帶 const 的話當(dāng)然不用去掉,但是一旦 ParamType 中帶有 const 就應(yīng)該去掉實(shí)參自帶的 const 。
- 「如果 expr 具有引用類型,先將引用部分忽略」為什么引用部分可以忽略呢?
首先我們要明確,引用本身在C++中就是一個(gè)類型修飾符,用于表示一個(gè)對(duì)象的別名(盡管其底層實(shí)現(xiàn)是指針),但是引用的引用是沒有意義的。所以編譯器在推導(dǎo)類型時(shí)會(huì)忽略引用部分。
主要就是在C++標(biāo)準(zhǔn)中規(guī)定,引用的引用會(huì)折疊成一個(gè)引用,具體的規(guī)則如下:
T& &
和T& &&
折疊為T&
。我們忽略引用部分就是因?yàn)檫@一條T&& &
折疊為T&
T&& &&
折疊為T&&