c++中的typename與class

來源:互聯網
上載者:User

   在泛型程式設計的形參表中,關鍵字typename和class具有相同的含義,可以相互使用,兩個關鍵字都可以在同一模板形參表中使用: 

1.  typename用在模板定義裡,標明其後的模板參數是型別參數。

template<typename T,class U> calc (const T&, const U& ); // 定義一個返回參數中較大者的通用函數template <typename T>const T& max(const T& x, const T& y){  if (y < x) {    return x;  }  return y;}

這種情況下,typename可用另一個的等效關鍵字class代替,如下片段所示:

// 定義一個返回參數中較大者的通用函數template <class T>const T& max(const T& x, const T& y){  if (y < x) {    return x;  }  return y;}
   引入這個關鍵字主要是為了避免class可能給人帶來的混淆:

 使用關鍵字typdef 代替關鍵字class制定模板類型形參也許更為直觀,畢竟,可以使用內建類型(而不僅僅只是類類型)作為實際的類型形參,而且,更清楚地聲明後面的名字是一個類型名。關鍵字typedef作為標準c++的組成部分假如到c++中的,因此舊的程式可能只是用class用來修飾泛型程式設計的形參類型。

2, 模板中標明“內嵌依賴類型名”:內嵌依賴類型名(nested dependent type name)

   .本來typename的用法就是這麼簡單, 但是STL原始碼中還有typename的一種不常見的用法:

例1:

請看SGI STL裡的一個例子, 只是STL中count範型演算法的實現:

template <class _InputIter, class _Tp>typename iterator_traits<_InputIter>::difference_typecount(_InputIter __first, _InputIter __last, const _Tp& __value) {  __STL_REQUIRES(_InputIter, _InputIterator);  __STL_REQUIRES(typename iterator_traits<_InputIter>::value_type,                 _EqualityComparable);  __STL_REQUIRES(_Tp, _EqualityComparable);  typename iterator_traits<_InputIter>::difference_type __n = 0;  for ( ; __first != __last; ++__first)    if (*__first == __value)      ++__n;  return __n;}
這裡有三個地方用到了typename:傳回值、參數、變數定義。分別是:

    typename iterator_traits<_InputIter>::difference_type

    typename iterator_traits<_InputIter>::value_type

    typename iterator_traits<_InputIter>::difference_type __n = 0;     difference_type, value_type就是依賴於_InputIter(模板型別參數)的類型名。源碼如下:

 template <class _Iterator>struct iterator_traits {  typedef typename _Iterator::iterator_category iterator_category;  typedef typename _Iterator::value_type        value_type;  typedef typename _Iterator::difference_type   difference_type;  typedef typename _Iterator::pointer           pointer;  typedef typename _Iterator::reference         reference;};
內嵌是指定義在類名的定義中的。以上difference_type和value_type都是定義在iterator_traits中的。

    依賴是指依賴於一個模板參數。typename iterator_traits<_InputIter>::difference_type中difference_type依賴於模板參數_InputIter.

    類型名是指這裡最終要指出的是個類型名,而不是變數。例如iterator_traits<_InputIter>::difference_type完全有可能是類iterator_traits<_InputIter>類裡的一個static對

    象。而且當我們這樣寫的時候,C++預設就是解釋為一個變數的。所以,為了和變數區分,必須使用typename告訴編譯器。

    那麼是不是所有的T::type_or_variable, 或者tmpl<T>:type_or_variable都需要使用typename呢。不是,有以下兩個例外。 3 例外

    (1)類模板定義中的基類列表。     例如

template<class T>class Derived: public Base<T>::XXX{...}
(2)類模板定義中的初始化列表。

Derived(int x) : Base<T>::xxx(x){...}
為什麼這裡不需要呢。因為編譯器知道這裡需要的是類型還是變數,

    (1)基類列表裡肯定是類型名,(2)初始化列表裡肯定是成員變數名。 例2:

在模板定義內部指定類型。如下面代碼:

typename<class Parm,class U>Parm fcn(Parm* array,U value){     Parm::size_type *p;     //如果Parm::size_type是一個類型,這句話的意思就是聲明一個變數     //如果如果Parm::size_type是一個變數(對象),這句話的意思就是乘法運算}

假如像上面的代碼一樣在模板中使用這種語句,則編譯器將無法辨別Parm::size_type是一個變數還是一個類型。所以必須顯式的告訴編譯器:

Parm::size_type是一個類型:

   則函數模板變為如下所示:

typename<class Parm,class U>Parm fcn(Parm* array,U value){    typename Parm::size_type *p;}

部分內容來自http://c.chinaitlab.com/cc/basic/200907/788872.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.