使用模板時,在申明模板型別引數時,我們經常有如下兩種申明方式:
// 方式一
template ctest;
// 方式二
template ctest;
這兩種寫法並沒有任何區別,都表示 t 是模板型別引數,可以是任何型別,包括使用者自定義型別或是語言的基本型別。雖然用於模板型別引數申明時作用完全相同,但是仍建議使用 typename,因為 typename 的字面意義即表示型別名稱,更加符合其語義。而 class 則多用於類的申明,而非模板型別引數。當然,如果原有專案中均使用 class,那麼請與原有專案風格保持一致。
在 template 宣告式中,用於申明模板型別引數時,class 與 typename 作用完全一致。當然,因為前者字元數少,可能會有人傾向於使用 class。但有些時候,typename 卻是不可被替換成 class。
假設有個函式模板,接受乙個容器 c 為引數,這個容器內部定義了乙個型別 a。stl 容器內部會定義 5 種迭代器型別(iterator_category, value_type, difference_type, pointer, reference),即迭代器中定義的型別。這裡a可以是其中任何乙個,也可是使用者自定義型別,但假設不是基本型別。現在看這個函式模板的定義:
template
// 建議使用 typename
void
func
(const c& container)
考慮上面模板定義式中間那行**,對於開發者而言,可以很明顯地推斷出**的含義,x是乙個a型別的指標。但是對於編譯器而言,在沒有明確 c 的定義之前,是無法確定a是乙個巢狀於 c 中的型別,其實a可能是 c 內乙個靜態成員變數,假設x剛好是乙個全域性變數,那麼這行**也可以由編譯器解析為兩數相乘。
編譯器面對這樣的**如何處置?編譯器會這樣處理:如果在template中遇到乙個巢狀從屬型別名稱,即依賴於模板型別引數的型別,放在上面例子中對應 c::a,c::a 依賴於模板型別引數 c,它便假設這個名稱不是個型別,除非顯示告訴編譯器。所以預設情況下巢狀從屬型別名稱不是型別。如何顯示告知呢,可以使用 typename,這是它的第二重意義。在此對之前假設 a 不是基本型別,因為基本型別並不依賴其它型別。
正確的函式模板定義如下:
template
void
func
(const c& container)
到這裡,想必對 typename 的第二重含義已經基本了解,這也是 typename 與 class 的不同之處,模板中當出現巢狀從屬型別名稱時須使用 typename 幫助編譯器識別。
模板中當出現巢狀從屬型別名稱時須使用 typename 幫助編譯識別,這一規則也存在例外。typename 不可以出現在 base classes list(所繼承的基類成員列表)內的巢狀從屬型別名稱之前,也不可以在 member initialization list(成員初始化列表)中作為 base class 修飾符。例如:
templateclass derived: public base::nested
};
(1)申明模板引數時,class 和 typename 可以互換,建議使用 typename,因為從字面更加符合語義;
(2)巢狀從屬型別名稱(nested dependent type name)須使用 typename 來標識,但不能在所繼承的基類成員列表和成員初始化列表中使用。
[1] effective c++:改善程式與設計的55個具體做法(第3版 中文版)[m].條款四十二:了解typename的雙重意義
[2] 陳剛.c++高階高階教程[m].武漢:武漢大學出版社,2008.c6.9 typename的用法
[3] 《stl原始碼剖析》筆記:迭代器
條款42 了解typename的雙重含義
typename在很多種情況下與class是完全相同的,例如下面的使用 1 templame2 3 template 4 條款42 了解typename的雙重含義 1 template2 void print2nd const c containter 310 上面這個式子是無法通過編譯的 這裡的c...
探索「雲計算」的雙重含義 節選
探索 雲計算 的雙重含義 資訊 公用電網 之說只屬於 雲計算 含義中的一方面,於尼古拉斯 卡爾的 it不再重要 還有一種更通俗的理解,把所有的本地的事,都可以放到雲端來完成就是雲計算了。未來的電腦將不需要主機,只需要乙個顯示器。原來機箱裡的東西哪去了?它們將全部儲存在 雲計算 中。一些遊戲玩家渴望追...
c typename和class的區別
相信學習c 的人對class這個關鍵字都非常明白,class用於定義類,在模板引入c 後,最初定義模板的方法為 template 在這裡class關鍵字表明t是乙個型別,後來為了避免class在這兩個地方的使用可能給人帶來混淆,所以引入了typename這個關鍵字,它的作用同 class一樣表明後面...