C++模板學習之typename


C++模板給這門編程語言帶來了全新的強大的能力。於是能夠進行所謂的模板元編程。因為人們發現,使用模板可以將一些邏輯讓編譯器在編譯期間內就完成,從而避免錯誤被漏到了運行時。

學好模板對理解C++開發以及理解都有非常大的好處。一些著名的C++庫如STL、boost等將模板的特性使用的淋漓盡致。

從頭學習模板,先看看如何定義一個模板。模板的聲明使用如下形式:

template<typename T> class Widget; // uses "typename"

這就表明Widget是一個模板類,在該類中,會使用到類型為T的某個類型。這個類型T由使用模板類Widget的使用者在使用時確定。當然,模板的聲明也可以使用關鍵字class代替typename進行

template<class T> class Widget; // uses "typename"

但是,《Effective C++》中建議我們盡量使用typename而不是class來聲明一個模板。因為class給人的感覺總像是T應該是一個類,或者說是用戶自定義的類型,而typename則更像是表明T可以是任意一種類型。雖然在C++編譯器看來,這兩種聲明方式沒有任何的區別,其意義是完全一樣的。

不過,typename關鍵字在模板中還有另一種用法,以下例子依然來自於《Effective C++》:

template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{ 
 // this is not valid C++!
 if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
 }
}

此處類型C期望是一個容器性質的類,比如STL中的那些容器,pritn2nd模板函數試圖將容器中的第二個元素打印出來,於是,在函數內定義了一個局部變量iter,一個const迭代器,來定位到容器中的第二個元素。但是這段代碼卻是不會被編譯器認可的,因為我們想當然地將C::const_iterator認為是一個類型了,按照我們對容器的印象(比如std::vector<T>::const_iterator)。然而編譯器並不知道C是個什么類型,C::const_iterator完全可能是C類型的一個成員變量。試想如果模板函數中是這樣的:

template<typename C>
void print2nd(const C& container)
{
 C::const_iterator * x;
 ...
}

如果C::const_iterator是一個類型,則定義了一個C::const_iterator類型的指針x,而如果C::const_iterator是類型C的一個成員變量呢,如果x正好是一個全局變量呢,這個表達式就是兩個變量的乘積了。此處產生歧義的原因就在於C::iterator意義不明確,它依賴於模板參數,我們將其稱為嵌套依賴名字(nested dependent name),為了消除歧義,C++規定,對於嵌套依賴名字,統統不解釋為類型,除非顯示聲明。這就是為什么說上面那段代碼有問題,因為編譯器不認為C::const_iterator是一個類型。那么如何顯示聲明C::iterator為一個類型呢,就是使用typename關鍵字!

template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{ 
 // this is not valid C++!
 if (container.size() >= 2) {
  typename C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
 }
}

這樣就對了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM