亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C++箴言:為類型信息使用特征類

2019-11-17 05:12:27
字體:
來源:轉載
供稿:網友

  STL 主要是由 containers(容器),iterators(迭代器)和 algorithms(算法)的 templates(模板)構成的,但是也有幾個 utility templates(實用模板)。其中一個被稱為 advance。advance 將一個指定的 iterator(迭代器)移動一個指定的距離:

template// move iter d units
void advance(IterT& iter, DistT d); // forward; if d < 0,
// move iter backward

  在概念上,advance 僅僅是在做 iter += d,但是 advance 不能這樣實現,因為只有 random access iterators(隨機訪問迭代器)支持 += Operation。不夠強力的 iterator(迭代器)類型不得不通過反復利用 ++ 或 -- d 次來實現 advance。

  你不記得 STL iterator categories(迭代器種類)了嗎?沒問題,我們這就做一個簡單回顧。對應于它們所支持的操作,共有五種 iterators(迭代器)。input iterators(輸入迭代器)只能向前移動,每次只能移動一步,只能讀它們指向的東西,而且只能讀一次。它們以一個輸入文件中的 read pointer(讀指針)為原型;C++ 庫中的 istream_iterators 就是這一種類的典型代表。output iterators(輸出迭代器)與此類似,只不過用于輸出:它們只能向前移動,每次只能移動一步,只能寫它們指向的東西,而且只能寫一次。它們以一個輸出文件中的 write pointer(寫指針)為原型;ostream_iterators 是這一種類的典型代表。這是兩個最不強力的 iterator categories(迭代器種類)。因為 input(輸入)和 output iterators(輸出迭代器)只能向前移動而且只能讀或者寫它們指向的地方最多一次,它們只適合 one-pass 運算。

  一個更強力一些的 iterator category(迭代器種類)是 forward iterators(前向迭代器)。這種 iterators(迭代器)能做 input(輸入)和 output iterators(輸出迭代器)可以做到的每一件事情,再加上它們可以讀或者寫它們指向的東西一次以上。這就使得它們可用于 multi-pass 運算。STL 沒有提供 singly linked list(單向鏈表),但某些庫提供了(通常被稱為 slist),而這種 containers(容器)的 iterators(迭代器)就是 forward iterators(前向迭代器)。TR1 的 hashed containers(哈希容器)的 iterators(迭代器)也可以屬于 forward category(前向迭代器)。

  bidirectional iterators(雙向迭代器)為 forward iterators(前向迭代器)加上了和向前一樣的向后移動的能力。STL 的 list 的 iterators(迭代器)屬于這一種類,set,multiset,map 和 multimap 的 iterators(迭代器)也一樣。

  最強力的 iterator category(迭代器種類)是 random access iterators(隨機訪問迭代器)。這種 iterators(迭代器)為 bidirectional iterators(雙向迭代器)加上了 "iterator arithmetic"(“迭代器運算”)的能力,也就是說,在常量時間里向前或者向后跳轉一個任意的距離。這樣的運算類似于指針運算,這并不會讓人感到驚奇,因為 random access iterators(隨機訪問迭代器)就是以 built-in pointers(內建指針)為原型的,而 built-in pointers(內建指針)可以和 random access iterators(隨機訪問迭代器)有同樣的行為。vector,deque 和 string 的 iterators(迭代器)是 random access iterators(隨機訪問迭代器)。

  對于五種 iterator categories(迭代器種類)中的每一種,C++ 都有一個用于識別它的 "tag strUCt"(“標簽結構體”)在標準庫中:

struct input_iterator_tag {};

struct output_iterator_tag {};

struct forward_iterator_tag: public input_iterator_tag {};

struct bidirectional_iterator_tag: public forward_iterator_tag {};

struct random_access_iterator_tag: public bidirectional_iterator_tag {};

  這些結構體之間的 inheritance relationships(繼續關系)是正當的 is-a 關系:所有的 forward iterators(前向迭代器)也是 input iterators(輸入迭代器),等等,這都是成立的。我們不久就會看到這個 inheritance(繼續)的功用。

  但是返回到 advance。對于不同的 iterator(迭代器)能力,實現 advance 的一個方法是使用反復增加或減少 iterator(迭代器)的循環的 lowest-common-denominator(最小共通特性)策略。然而,這個方法要花費 linear time(線性時間)。random access iterators(隨機訪問迭代器)支持 constant-time iterator arithmetic(常量時間迭代器運算),當它出現的時候我們最好能利用這種能力。

  我們真正想做的就是大致像這樣實現 advance:

template
void advance(IterT& iter, DistT d)
{
 if (iter is a random access iterator) {
  iter += d; // use iterator arithmetic
 } // for random access iters
 else {
  if (d >= 0) { while (d--) ++iter; } // use iterative calls to
  else { while (d++) --iter; } // ++ or -- for other
 } // iterator categories
}

  這就需要能夠確定 iter 是否是一個 random access iterators(隨機訪問迭代器),依次下來,就需要知道它的類型,IterT,是否是一個 random access iterators(隨機訪問迭代器)類型。換句話說,我們需要得到關于一個類型的某些信息。這就是 traits 讓你做到的:它們答應你在編譯過程中得到關于一個類型的信息。 traits 不是 C++ 中的一個要害字或預定義結構;它們是一項技術和 C++ 程序員遵守的慣例。建立這項技術的要求之一是它在 built-in types(內建類型)上必須和在 user-defined types(用戶定義類型)上一樣有效。例如,假如 advance 被一個指針(譬如一個 const char*)和一個 int 調用,advance 必須有效,但是這就意味著 traits 技術必須適用于像指針這樣的 built-in types(內建類型)。

  traits 對 built-in types(內建類型)必須有效的事實意味著將信息嵌入到類型內部是不可以的,因為沒有辦法將信息嵌入指針內部。那么,一個類型的 traits 信息,必須在類型外部。標準的方法是將它放到 template(模板)以及這個 template(模板)的一個或更多的 specializations(特化)中。對于 iterators(迭代器),標準庫中 template(模板)被稱為 iterator_traits:

template// template for information about
struct iterator_traits; // iterator types

  就像你能看到的,iterator_traits 是一個 struct(結構體)。根據慣例,traits 總是被實現為 struct(結構體)。另一個慣例就是用來實現 traits 的 structs(結構體)以 traits classes(這可不是我捏造的)聞名。

  iterator_traits 的工作方法是對于每一個 IterT 類型,在 struct(結構體)iterator_traits中聲明一個名為 iterator_category 的 typedef。這個 typedef 被看成是 IterT 的 iterator category(迭代器種類)。

  iterator_traits 通過兩部分實現這一點。首先,它強制要求任何 user-defined iterator(用戶定義迭代器)類型必須包含一個名為 iterator_category 的嵌套 typedef 用以識別適合的 tag struct(標簽結構體)。例如,deque 的 iterators(迭代器)是隨機訪問的,所以一個 deque iterators 的 class 看起來就像這樣:

template < ... >// template params elided
class deque {
 public:
  class iterator {
   public:
    typedef random_access_iterator_tag iterator_category;
    ...
  };
 ...
};

  然而,list 的 iterators(迭代器)是雙向的,所以它們是這樣做的:

template < ... >
class list {
 public:
 class iterator {
  public:
  typedef bidirectional_iterator_tag iterator_category;
  ...
 };
 ...
};

  iterator_traits 僅僅是簡單地模擬了 iterator class 的嵌套 typedef:

// the iterator_category for type IterT is whatever IterT says it is;
// see Item 42 for info on the use of "typedef typename"
template
struct iterator_traits {
 typedef typename IterT::iterator_category iterator_category;
 ...
};

  這樣對于 user-defined types(用戶定義類型)能很好地運轉。但是對于本身是 pointers(指針)的 iterators(迭代器)根本不起作用,因為不存在類似于帶有一個嵌套 typedef 的指針的東西。iterator_traits 實現的第二個部分處理本身是 pointers(指針)的 iterators(迭代器)。
  為了支持這樣的 iterators(迭代器),iterator_traits 為 pointer types(指針類型)提供了一個 partial template specialization(部分模板特化)。pointers 的行為類似 random access iterators(隨機訪問迭代器),所以這就是 iterator_traits 為它們指定的種類:


template// partial template specialization
struct iterator_traits// for built-in pointer types
{
 typedef random_access_iterator_tag iterator_category;
 ...
};

  到此為止,你了解了如何設計和實現一個 traits class:

  ·識別你想讓它可用的關于類型的一些信息(例如,對于 iterators(迭代器)來說,就是它們的 iterator category(迭代器種類))。

  ·選擇一個名字標識這個信息(例如,iterator_category)。

  ·提供一個 template(模板)和一系列 specializations(特化)(例如,iterator_traits),它們包含你要支持的類型的信息。

  給出了 iterator_traits ——實際上是 std::iterator_traits,因為它是 C++ 標準庫的一部分——我們就可以改善我們的 advance 偽代碼:

template
void advance(IterT& iter, DistT d)
{
 if (typeid(typename std::iterator_traits::iterator_category) ==
  typeid(std::random_access_iterator_tag))
 ...
}

  這個雖然看起來有點希望,但它不是我們想要的。在某種狀態下,它會導致編譯問題,這個問題我們以后再來研究它,現在,有一個更基礎的問題要討論。IterT 的類型在編譯期間是已知的,所以 iterator_traits::iterator_category 可以在編譯期間被確定。但是 if 語句還是要到運行時才能被求值。為什么要到運行時才做我們在編譯期間就能做的事情呢?它浪費了時間(嚴格意義上的),而且使我們的執行碼膨脹。

  我們真正想要的是一個針對在編譯期間被鑒別的類型的 conditional construct(條件結構)(也就是說,一個 if...else 語句)。碰巧的是,C++ 已經有了一個得到這種行為的方法。它被稱為 overloading(重載)。

  當你重載某個函數 f 時,你為不同的 overloads(重載)指定不同的 parameter types(形參類型)。當你調用 f 時,編譯器會根據被傳遞的 arguments(實參)挑出最佳的 overload(重載)?;旧?,編譯器會說:“假如這個 overload(重載)與被傳遞的東西是最佳匹配的話,就調用這個 f;假如另一個 overload(重載)是最佳匹配,就調用它;假如第三個 overload(重載)是最佳的,就調用它”等等??吹搅藛幔恳粋€針對類型的 compile-time conditional construct(編譯時條件結構)。為了讓 advance 擁有我們想要的行為方式,我們必須要做的全部就是創建一個包含 advance 的“內容”的重載函數的多個版本(此處原文有誤,根據作者網站勘誤修改——譯者注),聲明它們取得不同 iterator_category object 的類型。我為這些函數使用名字 doAdvance:

template// use this impl for
void doAdvance(IterT& iter, DistT d, // random access
std::random_access_iterator_tag) // iterators
{
 iter += d;
}

template// use this impl for
void doAdvance(IterT& iter, DistT d, // bidirectional
std::bidirectional_iterator_tag) // iterators
{
 if (d >= 0) { while (d--) ++iter; }
 else { while (d++) --iter; }
}

template// use this impl for
void doAdvance(IterT& iter, DistT d, // input iterators
std::input_iterator_tag)
{
 if (d < 0 ) {
  throw std::out_of_range("Negative distance"); // see below
 }
 while (d--) ++iter;
}

  因為 forward_iterator_tag 從 input_iterator_tag 繼續而來,針對 input_iterator_tag 的 doAdvance 版本也將處理 forward iterators(前向迭代器)。這就是在不同的 iterator_tag structs 之間繼續的動機。
(實際上,這是所有 public inheritance(公有繼續)的動機的一部分:使針對 base class types(基類類型)寫的代碼也能對 derived class types(派生類類型)起作用。)

  advance 的規范對于 random access(隨機訪問)和 bidirectional iterators(雙向迭代器)答應正的和負的移動距離,但是假如你試圖移動一個 forward(前向)或 input iterator(輸入迭代器)一個負的距離,則行為是未定義的。在我檢查過的實現中簡單地假設 d 是非負的,因而假如一個負的距離被傳入,則進入一個直到計數降為零的非常長的循環。在上面的代碼中,我展示了改為一個異常被拋出。這兩種實現都是正確的。未定義行為的詛咒是:你無法預知會發生什么。

  給出針對 doAdvance 的各種重載,advance 需要做的全部就是調用它們,傳遞一個適當的 iterator category(迭代器種類)類型的額外 object 以便編譯器利用 overloading resolution(重載解析)來調用正確的實現:

template
void advance(IterT& iter, DistT d)
{
 doAdvance( // call the version
  iter, d, // of doAdvance
  typename // that is
  std::iterator_traits::iterator_category() // apPRopriate for
 ); // iter's iterator
} // category

  我們現在能夠概述如何使用一個 traits class 了:

  ·創建一套重載的 "worker" functions(函數)或者 function templates(函數模板)(例如,doAdvance),它們在一個 traits parameter(形參)上不同。與傳遞的 traits 信息一致地實現每一個函數。

  ·創建一個 "master" function(函數)或者 function templates(函數模板)(例如,advance)調用這些 workers,傳遞通過一個 traits class 提供的信息。

  traits 廣泛地用于標準庫中。有 iterator_traits,當然,再加上 iterator_category,提供了關于 iterators(迭代器)的四塊其它信息(其中最常用的是 value_type )。還有 char_traits 持有關于 character types(字符類型)的信息,還有 numeric_limits 提供關于 numeric types(數值類型)的信息,例如,可表示值的最小值和最大值,等等。(名字 numeric_limits 令人有些希奇,因為關于 traits classes 更常用的慣例是以 "traits" 結束,但是它就是被叫做 numeric_limits,所以 numeric_limits 就是我們用的名字。)

  TR1引入了一大批新的 traits classes 提供關于類型的信息,包括 is_fundamental(T 是否是一個 built-in type(內建類型)),is_array(T 是否是一個 array type(數組類型)),以及 is_base_of(T1 是否和 T2 相同或者是 T2 的一個 base class(基類))。合計起來,TR1 在標準 C++ 中加入了超過 50 個 traits classes。

  Things to Remember

  ·traits classes 使關于類型的信息在編譯期間可用。它們使用 templates(模板)和 template specializations(模板特化)實現。

  ·結合 overloading(重載),traits classes 使得執行編譯期類型 if...else 檢驗成為可能。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
琪琪第一精品导航| 欧美一区二区视频97| 最近2019中文字幕第三页视频| 国产精品亚洲美女av网站| 日本精品一区二区三区在线| 亚洲激情第一页| 国产精品综合久久久| 久久人人爽亚洲精品天堂| 国产精品7m视频| 亚洲色图激情小说| 国产97在线观看| 久久久久www| 91精品国产乱码久久久久久久久| 欧美www视频在线观看| 2019av中文字幕| 91精品在线一区| 91精品美女在线| 日韩成人中文字幕在线观看| 成人免费看吃奶视频网站| 欧美中文在线视频| 欧美极品少妇xxxxⅹ喷水| 羞羞色国产精品| 欧美日韩中文字幕综合视频| 国产欧美日韩免费看aⅴ视频| 欧美精品xxx| www欧美xxxx| 国产精品9999| 色先锋资源久久综合5566| 亚洲欧美国产一区二区三区| 91av福利视频| 国产丝袜一区二区三区免费视频| 少妇av一区二区三区| 欧美性猛交xxx| 97国产一区二区精品久久呦| 国产精品无码专区在线观看| 久久99久久99精品免观看粉嫩| 国产精品成人v| 亚洲国产精品电影| 亚洲成**性毛茸茸| 欧美精品在线第一页| 91麻豆桃色免费看| 精品国产一区二区三区四区在线观看| 精品国产乱码久久久久久虫虫漫画| 亚洲第一区中文字幕| 成人综合国产精品| 久久久久久尹人网香蕉| 日韩在线视频免费观看| 亚洲国产成人精品久久久国产成人一区| 久久久久久噜噜噜久久久精品| 在线播放日韩精品| 中文字幕视频在线免费欧美日韩综合在线看| 日韩美女在线看| 欧美极品欧美精品欧美视频| 欧美电影免费观看网站| 国产福利精品av综合导导航| 57pao国产精品一区| 九色成人免费视频| 成人网在线免费看| 国产一区二区欧美日韩| 国产成人精品a视频一区www| 亚洲成人aaa| 国产精品亚洲视频在线观看| 久久久久北条麻妃免费看| 国产精品久久久久秋霞鲁丝| 欧美极品在线播放| 国内揄拍国内精品少妇国语| 亚洲天堂第一页| 亚洲人成电影网站色xx| 国产精品一区二区三| 日韩久久精品电影| 精品久久久久久久久久久久久| 久久视频在线观看免费| 亚洲欧美激情在线视频| 亚洲精品456在线播放狼人| 理论片在线不卡免费观看| 中文字幕在线看视频国产欧美在线看完整| 在线观看日韩专区| 亚洲免费成人av电影| 精品国偷自产在线| 日韩在线小视频| 91极品视频在线| 日韩美女视频免费在线观看| 国产视频久久久久久久| 亚洲国语精品自产拍在线观看| 成人av.网址在线网站| 亚洲精品第一国产综合精品| 91精品国产99久久久久久| 亚洲国产美女久久久久| 在线播放精品一区二区三区| 懂色av一区二区三区| 久久亚洲成人精品| 日韩精品在线观看网站| 亚洲自拍高清视频网站| 97免费在线视频| 色青青草原桃花久久综合| 91精品国产色综合久久不卡98口| 91精品国产综合久久久久久久久| 欧美日韩亚洲系列| 亚洲人成电影在线播放| 国产999在线观看| 精品久久久香蕉免费精品视频| 久久国产精品偷| 欧洲亚洲免费在线| 69**夜色精品国产69乱| 美女av一区二区| 亚洲精品免费一区二区三区| 另类少妇人与禽zozz0性伦| 日韩精品高清在线| 尤物yw午夜国产精品视频明星| 国产精品久久二区| 国产日韩在线精品av| 午夜免费在线观看精品视频| 色噜噜国产精品视频一区二区| 亚洲va欧美va国产综合剧情| 亚洲一区二区三区乱码aⅴ| 日韩在线观看免费高清完整版| 欧日韩在线观看| 日韩在线观看免费全| 国产不卡精品视男人的天堂| 亚洲国产精品999| 国产日韩综合一区二区性色av| 国产精品福利在线| 日韩高清电影免费观看完整版| 国产精品久久国产精品99gif| 日韩精品免费电影| 国产日韩在线一区| 亚洲第一精品久久忘忧草社区| 45www国产精品网站| 国产精品吴梦梦| 亚洲精品国产成人| 久久久久久久一| 中文字幕国产亚洲2019| 精品久久久久久久中文字幕| 国产欧美日韩最新| 欧美另类第一页| 夜夜嗨av一区二区三区四区| 国产精品网站入口| 成人精品一区二区三区电影免费| 综合欧美国产视频二区| 91禁国产网站| 欧美激情二区三区| 日韩精品免费电影| 日韩久久免费视频| 国产成人午夜视频网址| 国产精品色悠悠| 一本色道久久88精品综合| 国产成人精彩在线视频九色| 国产精品久久久久免费a∨大胸| 日韩在线欧美在线| 日韩av手机在线看| 国产午夜精品全部视频在线播放| 中文字幕日韩在线视频| 亚洲欧美福利视频| 欧美日韩国产成人高清视频| 色哟哟入口国产精品| 日韩毛片中文字幕| 国产精品揄拍一区二区| 成人乱人伦精品视频在线观看| 日韩乱码在线视频| 美女视频久久黄| 操人视频在线观看欧美| 欧美激情区在线播放| 草民午夜欧美限制a级福利片| 亚洲黄页网在线观看|