template之模板中class與typename區別
阿新 • • 發佈:2018-12-04
前言
在分析traits
程式設計之前, 我們需要對模板引數型別tempname
和class
有一定的瞭解, 要明白他們在哪些方面不同, 哪些方面相同, 這樣才能對體會到traits
程式設計的核心. 如果你已經明白了兩者, 那麼你可以直接看下一篇了.
相同之處
一般對模板引數型別typename
和class
認為是一樣的. 這兩者在引數型別中確實是一樣的. 你可以寫成
template<class T>
class point {};
也可以寫成
template<typename T>
class point {};
這兩者都是一樣的, 沒有區別. 兩者typename
和class
在引數型別中沒有不同
既然相同又為什麼定義這兩個符號呢?
- 最開始定義定義模板的方法就是template<class T> , 但是class畢竟都認為是一個類, 在使用時難免會有些點混淆, 也就定義了typename來標誌引數型別
- 最重要關於 typename可以使用巢狀依賴型別, 也就是型別可以巢狀使用. 這也是兩個的不同之處.
不同之處
typename
可以用在巢狀依賴中, 並且表示其型別, 而class
並沒有這樣的功能.
什麼是巢狀依賴? 我們以一個簡單的例項來看
template<class T>
class people
{
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
};
template<class T>
struct man
{
public:
typedef typename T::value_type value_type;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
void print()
{
cout << "man" << endl;
}
};
int main()
{
man<people<int>> Man;
Man.print();
exit(0);
}
以上就是typename
的巢狀使用. typename
告訴編譯器這不是一個函式, 也不是一個變數而是一個型別. 這裡使用typedef又將引數型別重新定義一次, 1. 增加了一層間接性, 2. 使用的時候也不需要在寫很長的程式碼.
這裡typename
是對people類中定義的型別進行了一次提取, 這裡將typename
改為class
就會出錯.
typename
主要的作用:
- 對於模板引數是類的時候,
typename
能夠提取出該類所定義的引數型別.
並不是所有的巢狀依賴型別都要加上typename
, 有一個例外 : 當繼承列表或成員初始化列表中對基類進行初始化的時候, 可以去掉typename
關鍵字
man(int x) : T::value_type(x) {}
總結
這裡對typename
做了一個淺顯的分析, 這也足夠我們可以分析traits
程式設計的基礎了. 我再將以上的分析做一個歸納.
typename
和class
在作為引數型別時用法一樣, 沒有區別typename
主要用於對巢狀依賴型別進行提取(萃取). 而class
沒有這樣的功能.typename
提取的一個例外是在繼承或成員初始化列表中對基類進行初始化時不用加typename
關鍵字