typename
typename作爲關鍵字有以下的用法:
-
作爲模板元編程使用
template <typename T>
template <class T>
void foo(const T& t)
{
// 聲明一個指向某個類型爲T::bar的對象的指針
typename T::bar * p;
}
typename的作用其實和class的作用的一致的,是class的替換(class並不是指的C++中的類Class),它是一種類型名,不是變量名,爲了能夠更好的理解和編寫代碼,而添加的一個關鍵字。
-
作爲類型名的聲明(至少寫者是這麼認爲)
template <class T>
void foo() {
T::iterator * iter;
// ...
}
粗略一看,T::iterator
可能是模板T中的一個變量(如枚舉變量),可能是結構體,也可能是某種類型,這一操作似乎就是定義一個指針變量iter,這麼想是沒錯的,但實際上是錯誤的。
在探索錯誤的原因前,我們應該知道實際上可以是以下三種中的任何一種類型:
- 靜態數據成員
- 靜態成員函數
- 嵌套類型
回到錯誤上來,如果說iterator是嵌套類型,這個寫法完全是沒有問題,但iterator是靜態數據成員呢?此時就會出現問題,這個時候的就變成了一個乘法表達式了。
此時,解決的辦法就是在前添加typename關鍵字,以此來表示是一個類型,同樣也稱爲嵌套依賴名字(nested dependent name);通用的規則很簡單:在你涉及到一個在 template(模板)中的嵌套依賴類型名( nested dependent type name)的任何時候,你必須把單詞 typename 放在緊挨着它的前面。
template <typename T>
void f(const T &t,typename T::iterator &iter){
......
}
上述代碼中,不是一個嵌套類型名(它不是嵌套在依賴於一個 template parameter(模板參數)的什麼東西內部的),所以不必添加typename關鍵字;而是一個嵌套類型名,故需要添加該關鍵字。
-
使用typename的規則
- typename在下面情況下禁止使用:
- 模板定義之外,即typename只能用於模板的定義中;
- 非限定類型,比如前面介紹過的
int
,vector<int>
之類,即一開始就標註了類型; - 基類列表中,比如
template<class T> class C1 : T::InnerType
不能在T::InnerType
前面加typename; - 構造函數的初始化列表中;
- 如果類型是依賴於模板參數的限定名,那麼在它之前必須加typename(除非是基類列表,或者在類的初始化成員列表中);
- 其它情況下typename是可選的,也就是說對於一個不是依賴名的限定名,該名稱是可選的,例如
vector<int> vi
;
typedef typename T::iterator iterator_type;
則現在,我們就能夠懂得這樣的定義具體的意思是什麼了。
參考
- C++ Primer
- C++中typename關鍵字的使用方法和注意事項
- C++箴言:理解typename的兩個含義