青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

twzheng's cppblog

『站在風口浪尖緊握住鼠標旋轉!』 http://www.cnblogs.com/twzheng

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  136 隨筆 :: 78 文章 :: 353 評論 :: 0 Trackbacks

[轉] typename 的兩個含義
【摘自】armman的專欄

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

  答案:沒什么不同。在聲明一個 template type parameter(模板類型參數)時,class 和 typename 意味著完全相同的東西。一些程序員更喜歡在所有的時間都用 class,因為它更容易輸入。其他人更喜歡 typename,因為它暗示著這個參數不必要是一個 class type(類類型)。少數開發者在任何類型都被允許的時候使用 typename,而把 class 保留給僅接受 user-defined types(用戶定義類型)的場合。但是從 C++ 的觀點看,class 和 typename 在聲明一個 template parameter(模板參數)時意味著完全相同的東西。

  然而,C++ 并不總是把 class 和 typename 視為等同的東西。有時必須使用 typename。為了理解這一點,我們不得不討論在一個 template(模板)中涉及到的兩種名字。

  假設我們有一個函數的模板,它能取得一個 STL-compatible container(STL 兼容容器)中持有的能賦值給 ints 的對象。進一步假設這個函數只是簡單地打印它的第二個元素的值。它是一個用糊涂的方法實現的糊涂的函數,而且就像下面寫的,它甚至不能編譯,但是請將這些事先放在一邊:

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
 }
}
  這個函數中的兩個 local variables(局部變量),iter 和 value。iter 的類型是 C::const_iterator,一個依賴于 template parameter(模板參數)C 的類型。一個 template(模板)中的依賴于一個 template parameter(模板參數)的名字被稱為 dependent names(依賴名字)。當一個 dependent names(依賴名字)嵌套在一個 class(類)的內部時,稱它為 nested dependent name(嵌套依賴名字)。C::const_iterator 是一個 nested dependent name(嵌套依賴名字)。實際上,它是一個 nested dependent type name(嵌套依賴類型名),也就是說,一個涉及到一個 type(類型)的 nested dependent name(嵌套依賴名字)。

  print2nd 中的另一個 local variable(局部變量)value 具有 int 類型。int 是一個不依賴于任何 template parameter(模板參數)的名字。這樣的名字以 non-dependent names(非依賴名字)聞名。

  nested dependent name(嵌套依賴名字)會導致解析困難。例如,假設我們更加愚蠢地以這種方法開始 print2nd:
template<typename C>
void print2nd(const C& container)
{
 C::const_iterator * x;
 ...
}
  這看上去好像是我們將 x 聲明為一個指向 C::const_iterator 的 local variable(局部變量)。但是它看上去如此僅僅是因為我們知道 C::const_iterator 是一個 type(類型)。但是如果 C::const_iterator 不是一個 type(類型)呢?如果 C 有一個 static data member(靜態數據成員)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是一個 global variable(全局變量)的名字呢?在這種情況下,上面的代碼就不是聲明一個 local variable(局部變量),而是成為 C::const_iterator 乘以 x!當然,這聽起來有些愚蠢,但它是可能的,而編寫 C++ 解析器的人必須考慮所有可能的輸入,甚至是愚蠢的。

  直到 C 成為已知之前,沒有任何辦法知道 C::const_iterator 到底是不是一個 type(類型),而當 template(模板)print2nd 被解析的時候,C 還不是已知的。C++ 有一條規則解決這個歧義:如果解析器在一個 template(模板)中遇到一個 nested dependent name(嵌套依賴名字),它假定那個名字不是一個 type(類型),除非用其它方式告訴它。缺省情況下,nested dependent name(嵌套依賴名字)不是 types(類型)。(對于這條規則有一個例外)

  記住這個,再看看 print2nd 的開頭:
template<typename C>void print2nd(const C& container)
{
 if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // this name is assumed to
  ... // not be a type
  這為什么不是合法的 C++ 現在應該很清楚了。iter 的 declaration(聲明)僅僅在 C::const_iterator 是一個 type(類型)時才有意義,但是我們沒有告訴 C++ 它是,而 C++ 就假定它不是。要想轉變這個形勢,我們必須告訴 C++ C::const_iterator 是一個 type(類型)。我們將 typename 放在緊挨著它的前面來做到這一點:

template<typename C> // this is valid C++
void print2nd(const C& container)
{
if (container.size() >= 2) {
typename C::const_iterator iter(container.begin());
...
}
}
  通用的規則很簡單:在涉及到一個在 template(模板)中的 nested dependent type name(嵌套依賴類型名)的任何時候,必須把單詞 typename 放在緊挨著它的前面。(重申一下,我待會兒要描述一個例外。)

  typename 應該僅僅被用于標識 nested dependent type name(嵌套依賴類型名);其它名字不應該用它。例如,這是一個取得一個 container(容器)和這個 container(容器)中的一個 iterator(迭代器)的 function template(函數模板):

template<typename C> // typename allowed (as is "class")
void f(const C& container, // typename not allowed
typename C::iterator iter); // typename required
  C 不是一個 nested dependent type name(嵌套依賴類型名)(它不是嵌套在依賴于一個 template parameter(模板參數)的什么東西內部的),所以在聲明 container 時它不必被 typename 前置,但是 C::iterator 是一個 nested dependent type name(嵌套依賴類型名),所以它必需被 typename 前置。

  "typename must precede nested dependent type names"(
typename 必須前置于嵌套依賴類型名)規則的例外是 typename 不必前置于在一個 list of base classes(基類列表)中的或者在一個 member initialization list(成員初始化列表)中作為一個 base classes identifier(基類標識符)的 nested dependent type name(嵌套依賴類型名)。例如:

template<typename T>
class Derived: public Base<T>::Nested { // base class list: typename not
 public: // allowed
  explicit Derived(int x)
  : Base<T>::Nested(x) // base class identifier in mem
  {
   // init. list: typename not allowed
    typename Base<T>::Nested temp; // use of nested dependent type
   ... // name not in a base class list or
  } // as a base class identifier in a
 ... // mem. init. list: typename required
};
  這樣的矛盾很令人討厭,但是一旦在經歷中獲得一點經驗,幾乎不會在意它。

  讓我們來看最后一個 typename 的例子,因為它在看到的真實代碼中具有代表性。假設我們在寫一個取得一個 iterator(迭代器)的 function template(函數模板),而且我們要做一個 iterator(迭代器)指向的 object(對象)的局部拷貝 temp,我們可以這樣做:
template<typename IterT>
void workWithIterator(IterT iter)
{
 typename std::iterator_traits<IterT>::value_type temp(*iter);
 ...
}
  不要讓 std::iterator_traits<IterT>::value_type 嚇倒你。那僅僅是一個 standard traits class(標準特性類)的使用,用 C++ 的說法就是 "the type of thing pointed to by objects of type IterT"(
被類型為 IterT 的對象所指向的東西的類型)。這個語句聲明了一個與 IterT objects 所指向的東西類型相同的 local variable(局部變量)(temp),而且用 iter 所指向的 object(對象)對 temp 進行了初始化。如果 IterT 是 vector<int>::iterator,temp 就是 int 類型。如果 IterT 是 list<string>::iterator,temp 就是 string 類型。因為 std::iterator_traits<IterT>::value_type 是一個 nested dependent type name(嵌套依賴類型名)(value_type 嵌套在 iterator_traits<IterT> 內部,而且 IterT 是一個 template parameter(模板參數)),我們必須讓它被 typename 前置。

  如果覺得讀 std::iterator_traits<IterT>::value_type 令人討厭,就想象那個與它相同的東西來代表它。如果像大多數程序員,對多次輸入它感到恐懼,那么就需要創建一個 typedef。對于像 value_type 這樣的 traits member names(特性成員名),一個通用的慣例是 typedef name 與 traits member name 相同,所以這樣的一個 local typedef 通常定義成這樣:

template<typename IterT> void workWithIterator(IterT iter)
{
 typedef typename std::iterator_traits<IterT>::value_type value_type;

 value_type temp(*iter);
 ...
}
  很多程序員最初發現 "typedef typename" 并列不太和諧,但它是涉及 nested dependent type names(嵌套依賴類型名)規則的一個合理的附帶結果。

  一些編譯器接受必需 typename 時它卻缺失的代碼;一些編譯器接受不許 typename 時它卻存在的代碼;還有少數的(通常是老舊的)會拒絕 typename 出現在它必需出現的地方。這就意味著 typename 和 nested dependent type names(嵌套依賴類型名)的交互作用會導致一些輕微的可移植性問題。

Things to Remember   
·在聲明 template parameters(模板參數)時,class 和 typename 是可互換的。
  
·用 typename 去標識 nested dependent type names(嵌套依賴類型名),在 base class lists(基類列表)中或在一個 member initialization list(成員初始化列表)中作為一個 base class identifier(基類標識符)時除外。

posted on 2007-05-09 11:47 譚文政 閱讀(427) 評論(0)  編輯 收藏 引用 所屬分類: C/C++
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            在线亚洲观看| 国产精品福利网| 亚洲高清视频在线| 亚洲综合不卡| 亚洲欧美日韩系列| 久久亚洲影音av资源网| 美女被久久久| 亚洲经典视频在线观看| 亚洲精选视频免费看| 一本色道**综合亚洲精品蜜桃冫| 亚洲午夜高清视频| 欧美在线视频一区二区三区| 久久亚洲风情| 欧美裸体一区二区三区| 国产精品自在欧美一区| 极品尤物久久久av免费看| 亚洲国产成人高清精品| 在线亚洲欧美| 老巨人导航500精品| 亚洲欧洲在线免费| 亚洲女爱视频在线| 欧美高清免费| 国产麻豆成人精品| 亚洲精品一区二区网址| 欧美在线看片a免费观看| 欧美激情视频一区二区三区在线播放| 在线一区二区三区四区| 久久天堂精品| 国产精品综合| 亚洲视频专区在线| 欧美成人黑人xx视频免费观看| 亚洲国产精品视频| 久久xxxx精品视频| 国产精品国产自产拍高清av王其| 亚洲激情欧美激情| 亚洲欧美电影院| 亚洲三级免费电影| 蜜桃av一区二区在线观看| 国产日韩欧美精品在线| 亚洲一区二区不卡免费| 免费永久网站黄欧美| 夜夜嗨一区二区三区| 99精品国产一区二区青青牛奶| av成人天堂| 亚洲福利视频一区二区| 中国成人黄色视屏| 欧美成人午夜免费视在线看片 | 夜夜嗨av一区二区三区四区| 久久九九精品| 欧美精品在线一区| 最新日韩精品| 久久久久久综合| 亚洲欧美激情视频| 欧美久久一级| 日韩一级精品| 亚洲风情在线资源站| 欧美一区二区大片| 国产视频不卡| 久久国产欧美日韩精品| 亚洲一区精品电影| 国产精品最新自拍| 亚洲午夜一区| 91久久夜色精品国产九色| 久久夜色撩人精品| 亚洲国产精品高清久久久| 久久久久久成人| 欧美一二三视频| 国产亚洲va综合人人澡精品| 久久久久亚洲综合| 欧美一区亚洲一区| 国产精品美女主播在线观看纯欲| 亚洲专区一二三| 亚洲亚洲精品在线观看| 国产伦精品一区二区三区视频黑人| 西西人体一区二区| 久久国产乱子精品免费女 | 午夜精品久久久久久99热| 一区二区激情小说| 国产精品一区二区你懂得| 久久久精品国产99久久精品芒果| 久久精品女人的天堂av| 91久久国产综合久久蜜月精品| 亚洲激情视频| 欧美午夜精品久久久久久孕妇| 亚洲免费中文| 久久都是精品| 99精品99| 亚洲欧美日韩精品久久亚洲区| 国产揄拍国内精品对白| 亚洲国产精品成人| 国产精品久久一卡二卡| 久久视频这里只有精品| 欧美国产成人在线| 欧美一级视频| 狂野欧美激情性xxxx| 日韩一级二级三级| 欧美一区在线看| 在线视频免费在线观看一区二区| 亚洲综合另类| 亚洲黄色性网站| 亚洲亚洲精品三区日韩精品在线视频| 久久久久国产精品厨房| 91久久精品美女高潮| 亚洲视频在线一区| 亚洲高清中文字幕| 香蕉国产精品偷在线观看不卡| 亚洲欧洲视频| 久久久精品一品道一区| 亚洲欧美综合一区| 欧美日韩91| 国产日产亚洲精品| 亚洲精品久久| 在线成人中文字幕| 亚洲一区二区视频在线观看| 亚洲经典视频在线观看| 久久高清一区| 欧美影院视频| 国产精品蜜臀在线观看| 艳妇臀荡乳欲伦亚洲一区| 亚洲三级国产| 久久这里有精品视频| 欧美一级专区| 欧美日韩国产系列| 亚洲国产精品第一区二区三区| 国产日韩精品在线观看| 亚洲精品一区二区三区99| 亚洲国产高清高潮精品美女| 亚洲影视在线播放| 亚洲欧美日韩国产综合在线 | 亚洲国产高清aⅴ视频| 国产女主播一区二区三区| 日韩一级在线观看| 99国产精品久久久久久久久久 | 久久深夜福利免费观看| 国产精品美女999| 9色国产精品| 亚洲视频日本| 欧美丝袜一区二区| 夜夜爽av福利精品导航| 亚洲一区二区三区四区五区黄 | 老鸭窝91久久精品色噜噜导演| 玖玖玖国产精品| 黄色精品网站| 久久久久国产免费免费| 狂野欧美性猛交xxxx巴西| 黄色成人免费观看| 久久性色av| 最近中文字幕日韩精品 | 久久噜噜噜精品国产亚洲综合| 国产欧美va欧美va香蕉在| 午夜影院日韩| 久久综合久久综合久久| 在线看片一区| 欧美精品亚洲一区二区在线播放| 亚洲免费电影在线观看| 性色av一区二区三区| 国产片一区二区| 久久久久久亚洲精品不卡4k岛国| 欧美不卡高清| 一区二区三区免费看| 国产精品国产三级国产a| 亚洲一区二区精品| 国产一区二区中文| 久久青青草原一区二区| 欧美激情网站在线观看| 在线综合视频| 国产日韩欧美一区二区| 久久一区二区三区av| 亚洲精品日产精品乱码不卡| 中文日韩电影网站| 国产精品一区二区视频| 久久永久免费| 9色porny自拍视频一区二区| 久久久综合精品| 99热在线精品观看| 国产日韩在线看| 欧美精品 国产精品| 欧美一区深夜视频| 欧美激情一区二区三级高清视频| 亚洲欧美日韩视频一区| 亚洲国产精品专区久久| 国产欧美一区视频| 欧美日韩久久不卡| 久久久精品999| 在线视频你懂得一区二区三区| 美女被久久久| 欧美专区在线观看一区| 野花国产精品入口| 伊人蜜桃色噜噜激情综合| 欧美日韩中文在线| 久久久久国色av免费看影院| 国产精品99久久久久久白浆小说| 欧美不卡福利| 久久久久久久综合色一本| 一区二区欧美亚洲| 亚洲第一福利在线观看| 国产午夜精品视频| 国产精品成人免费视频 | 欧美新色视频| 欧美激情精品久久久久久大尺度|