關鍵字②:typename

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,這麼想是沒錯的,但實際上是錯誤的。

在探索錯誤的原因前,我們應該知道T::iterator實際上可以是以下三種中的任何一種類型:

  • 靜態數據成員
  • 靜態成員函數
  • 嵌套類型

回到錯誤上來,如果說iterator是嵌套類型,這個寫法完全是沒有問題,但iterator是靜態數據成員呢?此時就會出現問題,這個時候的T::iterator * iter就變成了一個乘法表達式了。

此時,解決的辦法就是在T::iterator * iter前添加typename關鍵字,以此來表示T::iterator是一個類型,同樣也稱爲嵌套依賴名字(nested dependent name);通用的規則很簡單:在你涉及到一個在 template(模板)中的嵌套依賴類型名( nested dependent type name)的任何時候,你必須把單詞 typename 放在緊挨着它的前面。

template <typename T>

void f(const T &t,typename T::iterator &iter){
    ......
}

上述代碼中,t不是一個嵌套類型名(它不是嵌套在依賴於一個 template parameter(模板參數)的什麼東西內部的),所以不必添加typename關鍵字;而T::iterator * iter是一個嵌套類型名,故需要添加該關鍵字。

 

  • 使用typename的規則

  • typename在下面情況下禁止使用:
    • 模板定義之外,即typename只能用於模板的定義中;
    • 非限定類型,比如前面介紹過的intvector<int>之類,即一開始就標註了類型;
    • 基類列表中,比如template<class T> class C1 : T::InnerType不能在T::InnerType前面加typename;
    • 構造函數的初始化列表中;
  • 如果類型是依賴於模板參數的限定名,那麼在它之前必須加typename(除非是基類列表,或者在類的初始化成員列表中);
  • 其它情況下typename是可選的,也就是說對於一個不是依賴名的限定名,該名稱是可選的,例如vector<int> vi
typedef typename T::iterator iterator_type;

則現在,我們就能夠懂得這樣的定義具體的意思是什麼了。

 

參考

  1. C++ Primer
  2. C++中typename關鍵字的使用方法和注意事項
  3. C++箴言:理解typename的兩個含義

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章