typename和c++lass在c++模板中大部分情況可互換,但在特定場景有區(qū)別。1. 聲明模板類型參數(shù)時兩者等價,僅風格不同;2. 引用嵌套依賴類型時必須用typename,如typename t::value_type;3. 模板模板參數(shù)只能使用class關鍵字。
在C++模板中,typename和class這兩個關鍵字經常被混用,尤其是在聲明類型參數(shù)的時候。很多人會疑惑:它們到底有沒有區(qū)別?其實,在大多數(shù)情況下,它們是可以互換使用的,但在某些特定場景下,選擇哪一個確實會影響代碼的正確性。
1. 聲明模板類型參數(shù)時,typename和class基本等價
當你在定義一個模板時,比如:
template <class T> void foo(T t); template <typename T> void bar(T t);
這兩種寫法是完全等價的,編譯器不會有任何區(qū)別對待。你可以根據個人或團隊風格選擇使用哪一個。
立即學習“C++免費學習筆記(深入)”;
一些開發(fā)者的習慣是:
- 用class表示期望傳入的是類類型(雖然并不強制)
- 用typename表示可以接受任意類型(包括內置類型)
但這些只是風格上的區(qū)別,并非語言規(guī)范的要求。
2. 在嵌套依賴類型中,必須使用typename
這是兩者之間最核心的一個區(qū)別。
如果你在一個模板內部引用了一個依賴于模板參數(shù)的類型中的嵌套類型,比如:
template <class T> void print(typename T::value_type* ptr);
這里就必須使用typename,否則編譯器會報錯。因為T::value_type是一個依賴類型,它是否真的是一個類型,在編譯器解析模板時無法確定。加上typename的作用就是告訴編譯器:“放心,這個T::value_type是個類型”。
常見錯誤示例:
template <class T> void func(T::iterator it); // 編譯失敗!缺少 typename
正確的寫法應該是:
template <class T> void func(typename T::iterator it); // 正確
注意:如果那個名字不是類型名(比如是靜態(tài)成員變量),就不能加typename,否則也會出錯。
3. 模板模板參數(shù)中只能使用class
還有一種情況是使用模板模板參數(shù)(template template parameter)時,你只能使用class關鍵字:
template <template <class> class Container> struct my_container;
或者更現(xiàn)代一點的寫法:
template <template <typename> class Container> struct my_container;
但不能寫成:
template <template <typename> typename Container> // 錯誤!語法不允許 struct my_container;
所以在這個特定語法結構里,無論你偏好哪個關鍵字,都只能使用class。
總結一下幾個關鍵點:
- 大多數(shù)時候typename和class可以互換使用
- 引用嵌套依賴類型時必須加typename
- 模板模板參數(shù)只能用class
- 風格上可以根據團隊約定統(tǒng)一選擇,保持一致性即可
基本上就這些了。看起來不復雜,但如果不注意細節(jié),很容易寫出讓編譯器“看不懂”的代碼。