您現在的位置是:首頁 > 網路遊戲首頁網路遊戲

C++typename的由來和用法

簡介千呼萬喚始出來,我們來看看C++標準:對於用於模板定義的依賴於模板引數的名稱,只有在例項化的引數中存在這個型別名,或者這個名稱前使用了typename關鍵字來修飾,編譯器才會將該名稱當成是型別

什麼是型別名稱

本文轉載自【微信公眾號:羽林君,ID:Conscience_Remains】經微信公眾號授權轉載,如需轉載與原文作者聯絡

C++typename的由來和用法

前言

在C++模板函式的使用過程中,我們經常可以看到一個typename的使用,例如這樣的操作

C++typename的由來和用法

但是除此之外,我們也會經常看到這樣的用法

C++typename的由來和用法

那麼這裡就要問大家,這C++類似的用法下有什麼區別呢,且聽我細細道來。

作者:良知猶存

轉載授權以及圍觀:歡迎新增微信公眾號:羽林君

由來分析

“typename”是一個C++程式設計語言中的關鍵字。當用於泛型程式設計時是另一術語“class”的同義詞。這個關鍵字用於指出模板宣告(或定義)中的非獨立名稱(dependent names)是型別名,而非變數名。

我們經常會這麼用 typename,這是一項C++程式語言的泛型程式設計(或曰“模板程式設計”)的功能,typename關鍵字用於引入一個模板引數。

template

const T& max(const T& x, const T& y)

{

if (y < x) {

return x;

}

return y;

}

在模板定義語法中關鍵字 class 與 typename 的作用完全一樣

template

這裡

class

關鍵字表明T是一個型別,後來為了避免

在這兩個地方的使用可能給人帶來混淆,所以引入了

typename

這個關鍵字,它的作用同

一樣表明後面的符號為一個型別。

那class使用就夠了,為什麼又引入了新的關鍵詞 typename ,關於這個問題,Stan Lippman 曾在其部落格中表示,最早 Stroustrup 使用

來宣告模板引數列表中的型別是為了避免增加不必要的關鍵字;後來委員會認為這樣混用可能造成概念上的混淆才加上了

關鍵字。

而使用

的作用就是告訴 c++ 編譯器,

後面的字串為一個型別名稱,而不是成員函式或者成員變數,這個時候如果前面沒有

,編譯器沒有任何辦法知道 T::LengthType 是一個型別還是一個成員名稱(靜態資料成員或者靜態函式),所以編譯不能夠透過。

問題浮現

那麼問題來了,什麼情況下,class定義之後,編譯不能透過呢?

void fun(const T& proto){

T::const_iterator it(proto。begin());

發生編譯錯誤是因為編譯器不知道

T::const_iterator

是個型別。萬一它是個變數呢?

的解析有著邏輯上的矛盾: 直到確定了

T

是什麼東西,編譯器才會知道

是不是一個型別; 然而當模板被解析時,

還是不確定的。這時我們宣告它為一個型別才能透過編譯:

而且在模板例項化之前,完全沒有辦法來區分它們,這絕對是滋生各種bug的溫床。這時C++標準委員會再也忍不住了,與其到例項化時才能知道到底選擇哪種方式來解釋以上程式碼,委員會決定引入一個新的關鍵字,這就是

千呼萬喚始出來,我們來看看C++標準:

對於用於模板定義的依賴於模板引數的名稱,只有在例項化的引數中存在這個型別名,或者這個名稱前使用了

typename

關鍵字來修飾,編譯器才會將該名稱當成是型別。除了以上這兩種情況,絕不會被當成是型別。

因此,如果你想直接告訴編譯器

是型別而不是變數,只需用

修飾:

typename T::const_iterator it(proto。begin());

這樣編譯器就可以確定

是一個型別,而不再需要等到例項化時期才能確定,因此消除了前面提到的歧義。

巢狀從屬型別

事實上型別

依賴於模板引數

, 模板中依賴於模板引數的名稱稱為

從屬名稱

(dependent name), 當一個從屬名稱巢狀在一個類裡面時,稱為

巢狀從屬名稱

(nested dependent name)。 其實

還是一個

巢狀從屬型別名稱

(nested dependent type name)。

巢狀從屬名稱是需要用

宣告的,其他的名稱是不可以用

宣告的。比如下面是一個合法的宣告:

void fun(const T& proto ,typename T::const_iterator it);

使用

在定義類模板或者函式模板時,

關鍵字都可以用於指定模板引數中的型別。也就是說,以下兩種用法是完全等價的。

template /* 。。。 */;

template /* 。。。 */;

既然

關鍵字已經存在,而且它也可以用於最常見的指定模板引數,那麼為什麼不廢除

這一用法呢?答案其實也很明顯,因為在最終的標準出來之前,所有已存在的書、文章、教學、程式碼中都是使用的是

,可以想像,如果標準不再支援

,會出現什麼情況。

使用關鍵字

代替關鍵字

指定模板型別形參更為直觀,畢竟,可以使用內建型別(非類型別)作為實際的型別形參,而且,

更清楚地指明後面的名字是一個型別名。但是,關鍵字

是作為標準C++的組成部分加入到C++中的,因此舊的程式更有可能只用關鍵字

這就是我分享的c++的typename,此外如果大家有什麼更好的思路,也歡迎分享交流哈。

Top