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

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

C++箴言:謹慎使用模板元編程

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

  template metaPRogramming (TMP)(模板元編程)是寫 template-based(基于模板)的運行于編譯期間的 C++ 程序的過程??紤]一下:一個 template metaprogram(模板元程序)是用 C++ 寫的運行于 C++ 編譯器中的程序。當一個 TMP 程序運行完成,它的輸出——從 templates(模板)實例化出的 C++ 源代碼片斷——隨后被正常編譯。

  假如你僅把它看作古怪的特性而沒有打動你,那你就不會對它有足夠的深入的思考。

  C++ 并不是為 template metaprogramming(模板元編程)設計的,但是自從 TMP 在 1990 年代早期被發現以來,它已被證實非常有用,使 TMP 變輕易的擴展很可能會被加入到語言和它的標準庫之中。是的,TMP 是被發現,而不是被發明。TMP 所基于的特性在 templates(模板)被加入 C++ 的時候就已經被引進了。所需要的全部就是有人注重到它們能夠以一種精巧的而且意想不到的方式被使用。

  TMP 有兩個強大的力量。首先,它使得用其它方法很難或不可能的一些事情變得輕易。第二,因為 template metaprograms(模板元程序)在 C++ 編譯期間執行,它們能將工作從運行時轉移到編譯時。一個結果就是通常在運行時才能被察覺的錯誤能夠在編譯期間被發現。另一個結果是 C++ 程序使得 TMP 的使用在以下每一個方面都能更有效率:更小的可執行代碼,更短的運行時間,更少的內存需求。(然而,將工作從運行時轉移到編譯時的一個結果就是編譯過程變得更長。使用 TMP 的程序可能比它們的 non-TMP 對等物占用長得多的編譯時間。)

  考慮STL的advance偽代碼。(在《C++箴言:為類型信息使用特征類》中。你現在可能需要讀該文,因為在本文中,我假設你已經熟悉了該文的內容。),我突出表示代碼中的偽代碼部分:

template<typename IterT, typename DistT>
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
}
  我們可以用 typeid 把偽代碼變成真正的代碼。這就產生了一個解決此問題的“常規”的 C++ 方法——它的全部工作都在運行時做:

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

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
}
  《C++箴言:為類型信息使用特征類》中指出這個 typeid-based(基于 typeid)的方法比使用 traits 的方法效率低,因為這個方法,(1)類型檢測發生在運行時而不是編譯期,(2)用來做運行時類型檢測的代碼必須出現在可執行代碼中。實際上,這個例子展示了 TMP 如何能比一個“常規”C++ 程序更高效,因為 traits 方法是 TMP。記住,traits 答應編譯時在類型上的 if...else 計算。

  我先前談及一些事情在 TMP 中比在“常規”C++ 中更簡單,而 advance 提供了這方面的一個例子。Item 47 提到 advance 的 typeid-based(基于 typeid)的實現可能會導致編譯問題,而這就是一個產生問題的例子:

std::list<int>::iterator iter;

...

advance(iter, 10); // move iter 10 elements forward;
// won't compile with above impl.
  考慮 advance 為上面這個調用生成的版本。用 iter 和 10 的類型取代 template parameters(模板參數)IterT 和 DistT 之后,我們得到這個:

void advance(std::list<int>::iterator& iter, int d)
{
if (typeid(std::iterator_traits<std::list<int>::iterator>::iterator_category) ==
typeid(std::random_access_iterator_tag)) {

iter += d; // error!
}
else {
if (d >= 0) { while (d--) ++iter; }
else { while (d++) --iter; }
}
}
  問題在突出顯示的行,使用了 += 的那行。在當前情況下,我們試圖在一個 list<int>::iterator 上使用 +=,但是 list<int>::iterator 是一個 bidirectional iterator(雙向迭代器)(參見《C++箴言:為類型信息使用特征類》),所以它不支持 +=。只有 random access iterators(隨機訪問迭代器)才支持 +=。此時,我們知道我們永遠也不會試圖執行那個 += 行,因為那個 typeid 檢測對于 list<int>::iterators 永遠不成立,但是編譯器被責成確保所有源代碼是正確的,即使它不被執行,而當 iter 不是一個 random access iterator(隨機訪問迭代器)時 "iter += d" 是不正確的。traits-based(基于 traits)的 TMP 解決方案與此對比,那里針對不同類型的代碼被分離到單獨的函數中,其中每一個都只使用了可用于它所針對的類型的操作。

  TMP 已經被證實是 Turing-complete(圖靈完備)的,這意味著它強大得足以計算任何東西。使用 TMP,你可以聲明變量,執行循環,編寫和調用函數,等等。但是這些結構看起來與其在“常規”C++ 中的樣子非常不同。例如,《C++箴言:為類型信息使用特征類》展示了 if...else 條件在 TMP 中是如何通過 templates(模板)和 template specializations(模板特化)被表達的。但那是 assembly-level(匯編層次)的 TMP。針對 TMP 的庫提供了一種更高層次的語法,雖然還不至于讓你把它誤認為是“常規”C++。

  為了一窺其它東西在 TMP 中如何工作,讓我們來看看 loops(循環)。TMP 中沒有真正的 looping constrUCt(循環結構),因此 loops(循環)的效果是通過 recursion(遞歸)完成的。(假如你對 recursion(遞歸)感到不舒適,在你斗膽進入 TMP 之前一定要解決它。TMP 很大程度上是一個 functional language(函數性語言),而 recursion(遞歸)之于 functional language(函數性語言)就像電視之于美國流行文化:是密不可分的。)然而,甚至 recursion(遞歸)都不是常規樣式的,因為 TMP loops 不涉及 recursive function calls(遞歸函數調用),它們涉及 recursive template instantiations(遞歸模板實例化)。

  TMP 的 "hello world" 程序在編譯期間計算一個階乘。它不是一個很令人興奮的程序,不過,即使不是 "hello world",也有助于語言入門。TMP 階乘計算示范了通過 recursive template instantiation(遞歸模板實例化)實現循環。它也示范了在 TMP 中創建和使用變量的一種方法??矗?br />

template<unsigned n> // general case: the value of
struct Factorial { // Factorial<n> is n times the value
// of Factorial<n-1>

enum { value = n * Factorial<n-1>::value };

};

template<> // special case: the value of
struct Factorial<0> { // Factorial<0> is 1
enum { value = 1 };

};
  給出這個 template metaprogram(模板元程序)(實際上只是單獨的 template metafunction(模板元函數)Factorial),你可以通過引用 Factorial<n>::value 得到 factorial(n) 的值。

  代碼的循環部分出現在 template instantiation(模板實例化)Factorial<n> 引用 template instantiation(模板實例化)Factorial<n-1> 的地方。就像所有正確的 recursion(遞歸)有一個導致遞歸結束的非凡情況。這里,它就是 template specialization(模板特化)Factorial<0>。

  Factorial template 的每一個 instantiation(實例化)都是一個 struct,而每一個 struct 都使用 enum hack聲明了一個名為 value 的 TMP 變量。value 用于持有階乘計算的當前值。假如 TMP 有一個真正的循環結構,value 會在每次循環時更新。因為 TMP 在循環的位置使用 recursive template instantiation(遞歸模板實例化),每一個 instantiation(實例化)得到它自己的 value 的拷貝,而每一個拷貝擁有適合于它在“循環”中所處的位置的值。

  你可以像這樣使用 Factorial:

int main()
{
std::cout << Factorial<5>::value; // prints 120
std::cout << Factorial<10>::value; // prints 3628800
}
  假如你覺得這比吃了冰淇淋還涼快,你就具有了一個 template metaprogrammer(模板元程序員)應有的素質。假如 templates(模板)以及 specializations(特化)以及 recursive instantiations(遞歸實例化)以及 enum hacks 以及對類似 Factorial<n-1>::value 這樣的類型的需要使你毛骨悚然,好吧,你是一個不錯的常規 C++ 程序員。

  當然,Factorial 示范的 TMP 的效用大約就像 "hello world" 示范的任何常規編程語言的效用一樣。為了領會為什么 TMP 值得了解,更好地理解它能做什么是很重要的。這里是三個示例:

  Ensuring dimensional unit correctness(確保計量單位正確性)。在科學和工程應用中,計量單位(例如,質量,距離,時間,等等)被正確組合是基礎。例如,將一個代表質量的變量賦值給一個代表速度的變量是一個錯誤,但是用一個時間變量去除距離變量并將結果賦給一個速度變量就是正確的。使用 TMP,不論計算多么復雜,確保(在編譯期間)一個程序中所有計量單位組合都是正確的是有可能的。(這是一個如何用 TMP 進行早期錯誤診斷的例子。)這個 TMP 的使用的一個有趣的方面是能夠支持分數指數。這需要這個分數在編譯期間被簡化以便于編譯期能夠確認,例如,單位 time1/2 與單位 time4/8 是相同的。

  Optimizing matrix Operations(優化矩陣操作)?!禖++箴言:必須返回對象時別返回引用》中闡釋了一些函數,包括 operator*,必須返回新的 objects,而《C++箴言:從模板中分離出參數無關的代碼》一文中則引入了 SquareMatrix class,所以考慮如下代碼:

typedef SquareMatrix<double, 10000> BigMatrix;
BigMatrix m1, m2, m3, m4, m5; // create matrices and
... // give them values

BigMatrix result = m1 * m2 * m3 * m4 * m5; // compute their product
  用“常規”方法計算 result 需要四個臨時矩陣的創建,用于每一次調用 operator* 的結果。此外,獨立的乘法產生了一個四次循環遍歷矩陣元素的序列。使用一種與 TMP 相關的被稱為 eXPression templates(表達式模板)的高級模板技術,完全不改變上面的客戶代碼的語法,而消除臨時對象以及合并循環是有可能的。最終的軟件使用更少的內存而且運行速度戲劇性地更快。

  Generating custom design pattern implementations(生成自定義的設計模式實現)。像 Strategy(參見《C++箴言:考慮可選的虛擬函數的替代方法》),Observer,Visitor 等設計模式能用很多方法實現。使用一種被稱為 policy-based design(基于 policy 設計)的 TMP-based(基于 TMP)的技術,使得創建代表獨立的設計選擇的 templates ("policies") 成為可能,這種 templates 能以任意的方法組合以產生帶有自定義行為的模式實現。例如,這種技術經常用于答應幾個實現了 smart pointer behavioral(智能指針行為)的 policies 的 templates 生成(在編譯期間)數百個不同的 smart pointer(智能指針)類型。將類似設計模式和智能指針這樣的編程器件的范圍大大地擴展,這項技術是通常所說的 generative programming(產生式編程)的基礎。

  TMP 并不適合于每一個人。它的語法是不符合直覺的,工具支持也很弱(template metaprograms 的調試器?哈?。┳鳛橐粋€相對晚近才發現的“附屬”語言,TMP programming 的規則仍然帶有試驗性質。然而,通過將工作從運行時轉移到編譯時所提供的效率提升還是能給人留下深刻的印象,而表達在運行時很難或不可能實現的行為的能力也相當有吸引力。

  TMP 的支持程度在不斷提升。很可能在 C++ 的下一個版本中將對它提供直接的支持,而且 TR1 已經這樣做了。關于這一主題的書籍也即將開始出版(目前,C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond 已經出版——譯者注),而 web 上的 TMP 信息也正在保持增長。TMP 也許永遠不會成為主流,但是對于某些程序員——非凡是庫開發者——它幾乎必然會成為主料。

  Things to Remember

  ·template metaprogramming(模板元編程)能將工作從運行時轉移到編譯時,這樣就能夠更早察覺錯誤并提高運行時性能。

  ·TMP 能用于在 policy choices 的組合的基礎上生成自定義代碼,也能用于避免為非凡類型生成不適當的代碼。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
懂色av影视一区二区三区| 川上优av一区二区线观看| 日本久久久a级免费| 成人av.网址在线网站| 日韩在线播放一区| 国产91精品网站| 精品久久久999| 91精品综合视频| 91av在线影院| 久久久久999| 亚洲欧美日韩国产成人| 91sa在线看| 国产999精品| 日韩精品中文字幕有码专区| 曰本色欧美视频在线| 欧美黑人巨大精品一区二区| 日韩视频精品在线| 亚洲色图17p| 久久99精品久久久久久琪琪| 亚洲精品乱码久久久久久金桔影视| 亚洲一区二区久久久久久| 黑人巨大精品欧美一区二区一视频| 在线成人中文字幕| 亚洲精品视频网上网址在线观看| 成人写真视频福利网| 欧美成人精品激情在线观看| 欧美亚州一区二区三区| 亚洲一区二区三区视频播放| 高清欧美电影在线| 91在线精品播放| 亚洲精品一二区| 欧美视频中文字幕在线| 国产乱人伦真实精品视频| 久久免费福利视频| 国产精品无av码在线观看| 欧美激情视频一区二区三区不卡| 久久久久久久久久久久久久久久久久av| 久久精品视频在线| 日韩精品在线看| 伊人男人综合视频网| 欧美专区在线观看| 欧洲美女免费图片一区| 日本不卡高字幕在线2019| 亚洲精品国偷自产在线99热| xxx一区二区| 91黑丝在线观看| 97视频在线观看免费| 国产精品久久久久久av下载红粉| 午夜精品在线观看| 夜夜躁日日躁狠狠久久88av| 欧美精品成人91久久久久久久| 狠狠久久亚洲欧美专区| 国产一区二区三区视频免费| 亚洲第一区第一页| 欧洲永久精品大片ww免费漫画| 日韩精品在线观看一区二区| 91在线无精精品一区二区| 欧美精品在线免费| 搡老女人一区二区三区视频tv| 欧美性猛交xxxx乱大交极品| 狠狠色狠狠色综合日日五| 亚洲福利视频网| 69**夜色精品国产69乱| 亚洲精品成人网| 亚洲大胆人体视频| 欧美日韩亚洲精品一区二区三区| 日韩av在线网址| 国产一区视频在线播放| 日韩成人在线播放| 日韩欧美在线中文字幕| 欧美与欧洲交xxxx免费观看| 亚洲国产精品久久久久| 欧美精品久久久久久久| 中文字幕日韩免费视频| 亚洲精品mp4| 欧美日本国产在线| 精品中文字幕在线观看| 中文字幕免费精品一区高清| 亚洲精品日韩丝袜精品| 日韩欧美国产网站| 日韩视频免费观看| 亚洲高清av在线| 欧美午夜美女看片| 国产成人精彩在线视频九色| 中文字幕欧美精品在线| 日韩精品免费在线视频| 欧美另类69精品久久久久9999| 欧美在线激情视频| 欧美性猛交xxxx富婆弯腰| 欧美在线欧美在线| 精品久久久久久亚洲国产300| 欧美午夜视频在线观看| 韩剧1988在线观看免费完整版| 中文字幕一区电影| 亚洲高清一区二| 久青草国产97香蕉在线视频| 社区色欧美激情 | 国产午夜精品美女视频明星a级| 亚洲欧美一区二区精品久久久| 欧美性猛交99久久久久99按摩| 亚洲成年人在线| 欧美三级欧美成人高清www| 国内伊人久久久久久网站视频| 狠狠综合久久av一区二区小说| 国产精品久久久久久久久久99| 欧美第一淫aaasss性| 成人黄色av网| 亚洲欧美日韩网| 97精品久久久中文字幕免费| 国产精品久久久久久五月尺| 日韩女在线观看| 久久成人18免费网站| 欧亚精品在线观看| 亚洲免费视频一区二区| 91系列在线观看| 国产69精品久久久久久| 亚洲另类激情图| 亚洲人永久免费| 91成人在线观看国产| 91av在线网站| 欧美疯狂性受xxxxx另类| 国产成人一区二区三区电影| 亚洲sss综合天堂久久| 亚洲xxxxx电影| 亚洲欧美在线x视频| 欧美一级黑人aaaaaaa做受| 少妇激情综合网| 97视频在线观看播放| 亚洲视频欧美视频| 色综合久久久久久中文网| 亚洲福利在线观看| 九九热这里只有精品免费看| 欧亚精品在线观看| 九九热这里只有精品免费看| 欧美激情三级免费| 国产欧美日韩免费| 久久97精品久久久久久久不卡| 国产精品夜色7777狼人| 久久这里有精品| 久久高清视频免费| 日本精品免费观看| 日韩电影免费在线观看中文字幕| 国产欧美一区二区三区在线| 成人性生交大片免费观看嘿嘿视频| 国产精品网站入口| 亚洲精品电影网在线观看| 久久香蕉频线观| 亚洲欧美国产另类| 欧美成人亚洲成人日韩成人| 一区二区三区久久精品| 精品亚洲一区二区| 国产精品精品一区二区三区午夜版| 欧美日韩国产在线| 欧美日韩中文字幕日韩欧美| 欧美视频13p| 91免费看国产| 国内外成人免费激情在线视频网站| 精品欧美aⅴ在线网站| 国产精品久久久久久久久免费看| 久久成人人人人精品欧| 精品国产视频在线| 亚洲va国产va天堂va久久| 成人午夜在线影院| wwwwwwww亚洲|