學(xué)習(xí)元編程技術(shù)如何創(chuàng)建數(shù)據(jù)結(jié)構(gòu)和函數(shù),從而在編譯時(shí)進(jìn)行計(jì)算。通過《C 20模板元編程》,你將理解模板如何幫助你避免編寫重復(fù)代碼,模板是創(chuàng)建通用庫(kù)(如標(biāo)準(zhǔn)庫(kù)或Boost)的關(guān)鍵,這些庫(kù)可以在多種程序中使用。
本書的前幾章將為你提供關(guān)于模板和元編程基礎(chǔ)的知識(shí)。然后,你將開始練習(xí)編寫復(fù)雜的模板,并探索高級(jí)概念,如模板遞歸、模板實(shí)參推導(dǎo)、轉(zhuǎn)發(fā)引用、類型特征和條件編譯。在此過程中,你將學(xué)習(xí)如何編寫變參模板,以及如何使用C 20的約束和概念為模板實(shí)參提供約束和限制。最后,你將應(yīng)用C 元編程模板的知識(shí)實(shí)現(xiàn)各種元編程模式和技術(shù)。
到本書結(jié)束時(shí),你將學(xué)會(huì)如何編寫有效的模板,并在日常編程中使用元編程。
● 理解所有類型模板的語(yǔ)法
● 學(xué)習(xí)特化和實(shí)例化的工作原理
● 掌握模板實(shí)參推導(dǎo)和轉(zhuǎn)發(fā)引用
● 輕松編寫變參模板
● 掌握類型特征和條件編譯
● 使用 C 20 的約束和概念限制模板實(shí)參
● 實(shí)現(xiàn)CRTP、混入(mixin)和標(biāo)簽派發(fā)等模式
吳詠煒、祁宇、張銀奎聯(lián)袂推薦!
通過C 20模板元編程,將編譯期計(jì)算轉(zhuǎn)化為高性能代碼引擎,讓復(fù)雜泛型設(shè)計(jì)變得簡(jiǎn)單可維護(hù)。
解決模板難讀、難寫、難調(diào)試三大痛點(diǎn)。
玄之又玄,眾妙之門
大家都知道,AI可以寫代碼了。你用過嗎?感覺如何?
前不久,我在準(zhǔn)備GPU訓(xùn)練營(yíng)的試驗(yàn)程序時(shí),確實(shí)用AI寫了一些代碼,既有傳統(tǒng)的CPU端代碼,也有更現(xiàn)代的GPU端代碼。我用AI寫代碼的目的有兩個(gè),一是提高工作效率,二是親身測(cè)試AI寫代碼的能力。
親身測(cè)試一番之后,我有兩個(gè)比較強(qiáng)烈的感受。第一個(gè)感受是對(duì)于比較簡(jiǎn)單的任務(wù),AI確實(shí)可以寫出質(zhì)量不錯(cuò)的代碼,不僅速度快,而且準(zhǔn)確度很高,沒有誤拼等人類常犯的低級(jí)錯(cuò)誤。第二個(gè)感受是,隨著代碼量的上升,AI寫的代碼也開始具有人類代碼常有的問題,先是重復(fù),啰嗦,然后是有bug(錯(cuò)誤)。
眾所周知,AI領(lǐng)域吸引了大量的投資和優(yōu)秀的人才,新的成果不斷涌現(xiàn)。因此,我們比較難預(yù)測(cè)AI的代碼能力在2年后會(huì)怎么樣?在5年和10年后又會(huì)怎么樣?
AI技術(shù)的發(fā)展速度難以預(yù)測(cè),但是我覺得以下三個(gè)趨勢(shì)是比較確定的。首先,AI技術(shù)確實(shí)會(huì)改變軟件產(chǎn)業(yè)的格局,一些簡(jiǎn)單的軟件開發(fā)任務(wù)將AI化,因?yàn)槭褂肁I技術(shù)能大大提高編碼的效率,不再需要那么多的程序員來寫代碼。第二,隨著AI技術(shù)不斷被應(yīng)用到軟件開發(fā)領(lǐng)域,軟件的產(chǎn)量和軟件的代碼量都將隨之上升。而且,AI產(chǎn)生的代碼也是不完美并且存在瑕疵的。軟件團(tuán)隊(duì)里將需要很多調(diào)試工程師來定位各種稀奇古怪的問題。第三,在追求高性能、高可靠性的某些領(lǐng)域里,仍需要優(yōu)秀的人類程序員來編寫極端精致的代碼。就像在機(jī)器可以包餃子的今天,仍有某些餃子店使用人工包。
其實(shí),不管我的預(yù)測(cè)是否對(duì),一名好的程序員都應(yīng)該不斷錘煉自己的編碼能力,提高技術(shù)水平,讓自己寫出的代碼越來越好。
于是,可能有人問,我已經(jīng)能寫出很漂亮的代碼,什么樣的代碼算是更好呢?
的確,評(píng)價(jià)代碼好壞的標(biāo)準(zhǔn)有很多。在我看來,第一個(gè)硬指標(biāo)就是generic,也就是通用性。展開來說,很多代碼都有的一個(gè)通病就是長(zhǎng)相類似的代碼有很多份,結(jié)構(gòu)類似,但有差異,不完全相同。
我是信儒家的,但偶爾也會(huì)讀一點(diǎn)道家的作品,一般是在睡前讀,因?yàn)樽x道家的作品讀著讀著就昏昏欲睡了。為什么呢?因?yàn)榈兰业脑捯话愣急容^虛空。用時(shí)髦的話說,就是不接地氣,難以琢磨。比如一句道可道,非常道就有很多種解釋。
我對(duì)道家的這種態(tài)度持續(xù)了很多年,直到有一天,當(dāng)我領(lǐng)悟了計(jì)算機(jī)世界的一系列經(jīng)典案例和一個(gè)永恒規(guī)律后,我又看到了玄之又玄,眾妙之門。這八個(gè)字歸納得太好了,說出我心中所有,筆下所無(wú),改變了我對(duì)道家的態(tài)度。
什么是玄而又玄呢?傳統(tǒng)的解釋有很多種,對(duì)多數(shù)程序員來說,都不大好理解。
在我看來,玄就是抽象。玄之又玄,就是抽象了再抽象。
人類的大腦喜歡生動(dòng)具體的東西,比如小孩子都喜歡聽故事,無(wú)論是小馬過河還是后羿射日都有具體的場(chǎng)景、人和物。長(zhǎng)大了以后喜歡刷劇也是類似的原因。每部劇都在一個(gè)具體的時(shí)空中講一個(gè)故事。沒有哪部劇沒有人物,只有道可道,非常道。
因此,做抽象是很難的事情。也因此,很多代碼都是不夠抽象的,今天需要int類型的max()函數(shù),那么就寫個(gè)int類型的;明天需要float類型的,就把int類型的復(fù)制一份,改成float類型的。日積月累,整個(gè)項(xiàng)目里就有很多長(zhǎng)相類似的代碼了。
如何提煉這樣的代碼,消除重復(fù),把它們合眾為一呢?
傳統(tǒng)C 中的模板技術(shù)就是為解決這個(gè)問題而設(shè)計(jì)的,現(xiàn)代C 將其發(fā)揚(yáng)光大, 去除約束,增加功能,使其成為現(xiàn)代C 語(yǔ)言的一大亮點(diǎn)。
我認(rèn)識(shí)文波和榮華多年,他們都在C 語(yǔ)言和編程技術(shù)領(lǐng)域耕耘多年,孜孜不倦,滿懷深情。更加可貴的是,他們把熱愛轉(zhuǎn)化為實(shí)際的行動(dòng),以各種形式推動(dòng)技術(shù)的傳播和發(fā)展。他們?cè)诜g《C 模板》(第2版)之后,又將另一本模板編程的好書《C 20模板元編程》翻譯成中文,功莫大焉。
張銀奎
《軟件調(diào)試》和《軟件簡(jiǎn)史》的作者
譯 者 序
C 的演化與模板的歷史
自1979年Bjarne Stroustrup 創(chuàng)建C 以來,這門語(yǔ)言經(jīng)歷了多個(gè)重要的標(biāo)準(zhǔn)化版本,每一次演進(jìn)都帶來了新的特性和改進(jìn)。從C 98的標(biāo)準(zhǔn)化到C 11迎來現(xiàn)代C 編程范式,再到C 14、C 17的穩(wěn)定和擴(kuò)展,現(xiàn)在C 20作為一個(gè)里程碑式的更新,引入了概念(Concepts)、范圍(Ranges)、協(xié)程(Coroutines)等強(qiáng)大特性。其中,C 20對(duì)模板系統(tǒng)的擴(kuò)展和改進(jìn),使得泛型編程更加直觀、高效。
C 模板的歷史可以追溯到20世紀(jì)80年代后期,它最初是為了解決代碼復(fù)用的問題。1998年的C 標(biāo)準(zhǔn)(C 98)正式引入了模板,隨后在C 11中得到了重要增強(qiáng),如變參模板(Variadic Templates)、模板別名(Template Aliases)等。C 17進(jìn)一步引入了折疊表達(dá)式(Fold Expressions)和類模板實(shí)參推導(dǎo)(Class Template Argument Deduction,CTAD)。到了C 20,概念(Concepts)的加入使得模板的可讀性、可維護(hù)性大幅提升。
C 模板的優(yōu)勢(shì)
C 是一門支持多種編程范式的語(yǔ)言,包括:
●過程式編程(Procedural Programming)基于函數(shù)和過程的結(jié)構(gòu)化編程。
●面向?qū)ο缶幊?OOP)通過類、繼承和多態(tài)實(shí)現(xiàn)模塊化與復(fù)用。
●泛型編程(Generic Programming)借助模板編寫類型無(wú)關(guān)的代碼,提高代碼復(fù)用性和靈活性。
●函數(shù)式編程(Functional Programming)使用不可變數(shù)據(jù)和高階函數(shù),提升代碼可測(cè)試性和并發(fā)能力。
●元編程(Metaprogramming)利用編譯期計(jì)算優(yōu)化程序,提高運(yùn)行效率。
在這些范式中,模板技術(shù)是C 的核心特性,它賦予C 強(qiáng)大的泛型編程能力,使代碼適用于多種數(shù)據(jù)類型,而不需要冗余編寫。例如,標(biāo)準(zhǔn)模板庫(kù)(STL)的容器(如 std::vector、std::map)和算法(如 std::sort、std::find)均依賴模板實(shí)現(xiàn)。
C 模板的主要優(yōu)勢(shì)包括:
●編譯時(shí)多態(tài)(Compile-time Polymorphism)相比運(yùn)行時(shí)多態(tài)(如繼承與虛函數(shù)),模板允許編譯期進(jìn)行類型推導(dǎo)和優(yōu)化,從而提高執(zhí)行效率。
●編譯時(shí)計(jì)算(Compile-time Computation)利用模板元編程(TMP),C 能在編譯期執(zhí)行計(jì)算,減少運(yùn)行時(shí)開銷。例如,std::integral_constant 和 std::conditional 可用于選擇編譯期代碼路徑。
●代碼復(fù)用模板減少了重復(fù)代碼,提高了通用性。例如,std::enable_if 可用于 SFINAE(替換失敗非錯(cuò)誤),實(shí)現(xiàn)條件編譯。
模板的強(qiáng)大使其在現(xiàn)代C 開發(fā)中占據(jù)重要地位,特別是在高性能計(jì)算、游戲開發(fā)、底層系統(tǒng)編程等領(lǐng)域。掌握模板不僅能提升代碼質(zhì)量,還能幫助程序員深入理解C 語(yǔ)言的底層機(jī)制。
C 程序員的技能
對(duì)于希望深入掌握C 的開發(fā)者而言,理解模板是進(jìn)階C 編程的必經(jīng)之路。從泛型編程(Generic Programming)、模板元編程(Template Metaprogramming),到C 20 概念(Concepts),這些技術(shù)都在現(xiàn)代C 開發(fā)中占據(jù)了重要地位。
無(wú)論是編寫高效的庫(kù)函數(shù),還是優(yōu)化應(yīng)用程序的性能,模板都是必不可少的工具。例如,在高性能計(jì)算(HPC)、游戲開發(fā)、底層系統(tǒng)編程等領(lǐng)域,模板能夠提供無(wú)與倫比的靈活性和效率。掌握模板不僅能夠提高代碼質(zhì)量,還能幫助程序員更深入地理解C 語(yǔ)言的底層機(jī)制。
模板技術(shù)的學(xué)習(xí)建議
模板技術(shù)屬于編譯期編程,在學(xué)習(xí)過程中,建議結(jié)合反匯編,并善用Cpp Insights 等工具來觀察模板實(shí)例化和生成的代碼。
要系統(tǒng)學(xué)習(xí)模板技術(shù),僅靠一本書是不夠的。推薦閱讀以下書籍:
●《C Templates (第2版·中文版)》[C Templates: The Complete Guide, 2nd Edition, (美)David Vandevoorde、(德)Nicolai M. Josuttis、(美)Douglas Gregor著,何榮華、王文斌、張毅峰、楊文波譯,人民郵電出版社]經(jīng)典的C 模板書籍,全面介紹了模板技術(shù)。
●《編程原本》[Elements of ?Programming,(美)Alexnader Stepanov、(美) Paul McJones著,裘宗燕譯,人民郵電出版社]和亞歷山大的系列博文(https://www.stepanovpapers.com/)進(jìn)一步深入泛型編程。
●《C實(shí)戰(zhàn):核心技術(shù)與最佳實(shí)踐》(吳詠煒著,人民郵電出版社)現(xiàn)代C 最佳實(shí)踐。
此外,學(xué)習(xí)模板技術(shù)不能只依賴?yán)碚摚需要實(shí)踐。建議閱讀并改造以下模板庫(kù):
1. fmt(std::format的實(shí)現(xiàn))不依賴領(lǐng)域知識(shí),適合作為入門教材。
2. blaze高性能數(shù)學(xué)庫(kù)作者 Klaus Iglberger 是模板設(shè)計(jì)模式專家。
3. folly庫(kù)Andrei Alexandrescu 主導(dǎo),適合學(xué)習(xí)模板元編程。
4. cutlass C 模板庫(kù)Nvidia 出品,適用于深度學(xué)習(xí)優(yōu)化。
結(jié)語(yǔ)與感謝
C 模板的強(qiáng)大使得它成為現(xiàn)代C 開發(fā)的基石,而C 20的更新更是讓模板變得更易用、更強(qiáng)大。本書的目標(biāo)是幫助讀者全面理解C 20模板的核心概念,并掌握如何在實(shí)際開發(fā)中高效地應(yīng)用模板技術(shù)。希望本書能為你打開C 模板編程的大門,幫助你在C 領(lǐng)域更進(jìn)一步。
本書的出版離不開各方的支持。我們衷心感謝 Bjarne Stroustrup教授,他的貢獻(xiàn)不僅塑造了C 語(yǔ)言,也為全球開發(fā)者提供了深遠(yuǎn)的技術(shù)指導(dǎo)。
特別感謝清華大學(xué)出版社的編輯團(tuán)隊(duì),他們?cè)谛g(shù)語(yǔ)規(guī)范、技術(shù)表達(dá)及出版質(zhì)量方面提供了寶貴的支持,付出了大量的辛勤工作,確保本書得以高質(zhì)量呈現(xiàn)。我們也感謝C 社區(qū)的開發(fā)者們,你們的深入討論與實(shí)踐經(jīng)驗(yàn)為我們提供了極大的啟發(fā)。
盡管我們力求精確,但面對(duì)C 如此龐大而復(fù)雜的體系,難免仍有不足之處。我們誠(chéng)懇歡迎讀者通過出版社反饋意見,以便我們進(jìn)一步完善后續(xù)的修訂工作。希望本書能夠幫助廣大開發(fā)者更深入地理解C ,更高效地運(yùn)用這門強(qiáng)大語(yǔ)言。
獻(xiàn)給那些總是渴望學(xué)習(xí)更多的好奇心靈。
Marius Bancila
貢 獻(xiàn) 者
關(guān)于作者
Marius Bancila 是一位擁有20年經(jīng)驗(yàn)的軟件工程師,在業(yè)務(wù)應(yīng)用程序開發(fā)和其他領(lǐng)域都有豐富的解決方案經(jīng)驗(yàn)。他是Modern C Programming Cookbook和The Modern C Challenge的作者。他目前擔(dān)任軟件架構(gòu)師,專注于微軟技術(shù),主要使用C 和C#開發(fā)桌面應(yīng)用程序。他熱衷于與他人分享技術(shù)專長(zhǎng),因此自2006年起一直被認(rèn)定為微軟C MVP,后來還獲得了開發(fā)者技術(shù)領(lǐng)域的 MVP 稱號(hào)。Marius 居住在羅馬尼亞,活躍于各種在線社區(qū)。
關(guān)于審校者
Aleksei Goriachikh擁有超過8年的C 編程經(jīng)驗(yàn)。2012年從俄羅斯的新西伯利亞國(guó)立大學(xué)獲得數(shù)學(xué)碩士學(xué)位后,Aleksei曾參與一些計(jì)算數(shù)學(xué)和優(yōu)化領(lǐng)域的研究項(xiàng)目、某CAD系統(tǒng)的幾何內(nèi)核開發(fā),以及自動(dòng)駕駛的多線程庫(kù)開發(fā)。Aleksei 最近的專業(yè)興趣是硅前建模。
前 言
幾十年來,C 一直是世界上使用最廣泛的編程語(yǔ)言之一。它的成功不僅僅歸功于其提供的性能或者說它的易用性(許多人對(duì)此持不同意見),而更可能是由于它的多功能性。C 是一種通用的多范式編程語(yǔ)言,它融合了過程式、函數(shù)式和泛型編程。
泛型編程是一種編寫代碼的方式,例如函數(shù)和類等實(shí)體是按照稍后實(shí)例化的類型編寫的。這些泛型實(shí)體僅在需要作為實(shí)參具化為特定類型時(shí)才會(huì)實(shí)例化,這些泛型實(shí)體在C 中稱為模板。
元編程是一種編程技術(shù),它使用模板(以及C 中的constexpr函數(shù))在編譯期生成代碼,然后將其與剩余源代碼合并以便編譯最終程序。元編程意味著其輸入或輸出中至少有一個(gè)是類型。
正如《C 核心指南》(Bjarne Stroustrup和Herb Sutter維護(hù)的一份關(guān)于應(yīng)該做什么和不應(yīng)該做什么的文檔)中所描述的那樣,C 中的模板可謂聲名狼藉。然而,它們使得泛型庫(kù)成為可能,比如C 開發(fā)人員一直使用的C 標(biāo)準(zhǔn)庫(kù)。無(wú)論你是自己編寫模板,還是只使用他人編寫的模板(比如標(biāo)準(zhǔn)容器或算法),模板都很可能是你日常編碼的一部分。
本書旨在讓讀者對(duì)C 中可用的所有范圍內(nèi)的模板都有很好的理解(從基本語(yǔ)法到C 20中的概念),這是本書前兩部分的重點(diǎn)內(nèi)容。第Ⅲ部分會(huì)幫助你將新獲得的知識(shí)付諸實(shí)踐,并使用模板進(jìn)行元編程。
本書適讀人群
本書適合想要學(xué)習(xí)模板元編程的初學(xué)者、中級(jí)C 開發(fā)人員,以及希望快速掌握與模板相關(guān)的C 20新功能和各種慣用法和模式的高級(jí)C 開發(fā)人員。在開始閱讀本書之前,必須具備基本的C 編程經(jīng)驗(yàn)。
本書涵蓋內(nèi)容
第1章模板簡(jiǎn)介。通過幾個(gè)簡(jiǎn)單的例子介紹了C 中模板元編程的概念,討論了為什么我們需要模板以及模板的優(yōu)缺點(diǎn)。
第2章模板基礎(chǔ)。探討了C 中所有形式的模板:函數(shù)模板、類模板、變量模板和別名模板。我們討論了其中每一個(gè)的語(yǔ)法和它們?nèi)绾喂ぷ鞯募?xì)節(jié)。此外,還討論了模板實(shí)例化和特化的關(guān)鍵概念。
第3章變參模板。專門介紹了變參模板,即具有可變數(shù)量模板形參的模板。我們?cè)敿?xì)討論了變參函數(shù)模板、變參類模板、變參別名模板和變參變量模板、形參包及其展開方式,以及幫助我們簡(jiǎn)化編寫變參模板的折疊表達(dá)式。
第4章高級(jí)模板概念。對(duì)一系列高級(jí)模板概念進(jìn)行了分組,比如依賴名稱和名稱查找、模板實(shí)參推導(dǎo)、模板遞歸、完美轉(zhuǎn)發(fā)、泛型和模板lambda函數(shù)。通過了解這些主題,讀者將能夠極大地?cái)U(kuò)展他們可以閱讀或編寫的模板的種類。
第5章類型特征和條件編譯。專門討論類型特征。讀者將了解類型特征、標(biāo)準(zhǔn)庫(kù)提供的特征以及如何使用它們解決不同的問題。
第6章概念和約束。介紹了新的C 20機(jī)制,通過概念和約束定義模板實(shí)參的需求。你將了解指定約束的各種方法。此外,還概述了C 20標(biāo)準(zhǔn)概念庫(kù)的內(nèi)容。
第7章模式和慣用法。探討了一系列獨(dú)立的高級(jí)主題,即利用迄今為止學(xué)到的知識(shí)實(shí)現(xiàn)各種模式。我們探討了靜態(tài)多態(tài)、類型擦除、標(biāo)簽派發(fā)和模式的概念,比如奇異遞歸模板模式、表達(dá)式模板、混入和類型列表。
第8章范圍和算法。專注于理解容器、迭代器和算法,它們是標(biāo)準(zhǔn)模板庫(kù)的核心組件。你將在這里學(xué)習(xí)如何為其編寫泛型容器和迭代器類型以及通用算法。
第9章范圍庫(kù)。探討了新的C 20范圍庫(kù)及其關(guān)鍵特性,例如范圍、范圍適配器和約束算法。這些使我們能夠編寫更簡(jiǎn)單的代碼來處理范圍。此外,你還將在這里學(xué)習(xí)如何編寫自己的范圍適配器。
附錄是一個(gè)簡(jiǎn)短的結(jié)語(yǔ),提供了本書的總結(jié)。
問題答案包含了所有章節(jié)中習(xí)題的答案。
充分利用本書
要開始閱讀本書,首先需要對(duì)C 編程語(yǔ)言有一些基本的了解。需要了解有關(guān)類、函數(shù)、運(yùn)算符、函數(shù)重載、繼承、虛函數(shù)等的語(yǔ)法和基礎(chǔ)知識(shí)。不過,對(duì)模板知識(shí)不做要求,因?yàn)楸緯鴮念^開始教你一切。
本書中的所有代碼示例都是跨平臺(tái)的。這意味著你可以使用任何編譯器來構(gòu)建和運(yùn)行它們。然而,盡管許多代碼段適用于C 11編譯器,但也有一些代碼段需要兼容C 17或C 20的編譯器。因此,建議你使用支持C 20的編譯器版本,以便運(yùn)行所有示例。書中的示例已使用MSVC 19.30 (Visual Studio 2022)、GCC 12.1/13和Clang 13/14進(jìn)行了測(cè)試。如果你的機(jī)器上沒有這樣一個(gè)兼容C 20的編譯器,可以試著網(wǎng)上下載一個(gè)。我們推薦以下幾個(gè)方案:
●Compiler Explorer (https://godbolt.org/)
●Wandbox (https://wandbox.org/)
●C Insights (https://cppinsights.io/)
本書多次引用C Insights在線工具來分析編譯器生成的代碼。
如果你想檢查編譯器對(duì)不同版本的C 標(biāo)準(zhǔn)的支持,應(yīng)該參考頁(yè)面https://en.cppreference.com/w/cpp/compiler_support。
提及標(biāo)準(zhǔn)和延伸閱讀
在本書中,我們會(huì)多次提到C 標(biāo)準(zhǔn)。此文件版權(quán)歸國(guó)際標(biāo)準(zhǔn)化組織所有。官方的C 標(biāo)準(zhǔn)文檔可以從這里購(gòu)買:https://www.iso.org/standard/79358.html。但是,C 標(biāo)準(zhǔn)的多個(gè)草案以及相應(yīng)源碼可以在GitHub上免費(fèi)獲得,網(wǎng)址為https://github.com/ cplusplus/draft?梢栽趆ttps://isocpp.org/ std/the-standard鏈接上找到有關(guān)C 標(biāo)準(zhǔn)的更多信息。
C Reference網(wǎng)站是C 開發(fā)人員的一個(gè)很好的在線資源,網(wǎng)址為https://en. cppreference.com/。它提供了直接派生自C 標(biāo)準(zhǔn)的C 語(yǔ)言的詳盡文檔。本書多次引用了C 參考中的內(nèi)容。C 參考的內(nèi)容是基于CC-BY-SA協(xié)議的,https://en.cppreference. com/w/Cppreference:Copyright/CC-BY-SA。
(在每一章的末尾,你會(huì)發(fā)現(xiàn)一個(gè)名為延伸閱讀的部分,該部分包含一份用作參考書目的閱讀材料清單,推薦閱讀以加深對(duì)所介紹主題的理解。)
下載示例代碼文件
可以從GitHub上下載本書的示例代碼文件,網(wǎng)址為https://github.com/ PacktPublishing/Template-Metaprogramming-with-CPP。也可以掃描封底二維碼下載。如果代碼有更新,將會(huì)在GitHub倉(cāng)庫(kù)中更新它。
下載彩圖
我們還提供了一個(gè)PDF文件,其中包含本書中使用的屏幕截圖和圖表的彩圖?梢栽诖颂幭螺d:https://packt.link/Un8j5。也可以掃描封底二維碼下載。
使用的約定
本書使用了一些文本約定。
文本中的代碼:表示文本中的代碼詞匯、數(shù)據(jù)庫(kù)表名、文件夾名、文件名、文件擴(kuò)展名、路徑名、虛擬URL、用戶輸入和Twitter用戶名/賬號(hào)標(biāo)識(shí)。這里有一個(gè)例子:這個(gè)問題可以通過將init設(shè)置為依賴名稱來解決。
代碼塊的格式如下:
template
structparser:base_parser
{
voidparse()
{
this->init(); // 正確
std::cout<<"parse\n";
}
};
按如下方式編寫任意命令行的輸入或輸出:
fatal error:recursive template instantiation exceeded maximum depth of 1024
use -ftemplate-depth=N to increase recursive template instantiation depth
粗體:表示一個(gè)新術(shù)語(yǔ)、一個(gè)重要單詞或你在屏幕上看到的單詞。例如,菜單或?qū)υ捒蛑械膯卧~以粗體顯示。這里有一個(gè)例子:容量為8,大小為0,頭部和尾部都指向索引0。
提示或重要說明
迭代器概念在第6章概念與約束中進(jìn)行了簡(jiǎn)要討論。
本書的參考文獻(xiàn)和問題答案可掃描封底二維碼下載。
馬里烏斯·班西拉(Marius Bancila)于2002年作為一名軟件開發(fā)人員開始了職業(yè)生涯,專注于使用 Visual C 、C# 和 .NET 框架開發(fā)桌面應(yīng)用程序。盡管多年來使用過許多編程和腳本語(yǔ)言(例如 Pascal、C、C 、Java、JavaScript、C#、VB.NET、MC 、C /CLI、HTML、CSS 等),但 C 始終是他的首選語(yǔ)言。目前他在挪威的Visma公司擔(dān)任 ERP 系統(tǒng)的系統(tǒng)架構(gòu)師。
Marius Bancila是Modern C Programming Cookbook和Modern C Challenge等多本C 技術(shù)圖書的作者,熱衷于與他人分享技術(shù)專長(zhǎng),并因此自2006年起連續(xù)18年被授予微軟MVP(最有價(jià)值專家)稱號(hào)。他撰寫了大量技術(shù)文章,創(chuàng)建和參與了多個(gè)開源項(xiàng)目,并活躍于各類在線開發(fā)者社區(qū)。
第Ⅰ部分 模板的核心概念
第1章 模板的簡(jiǎn)介 3
1.1 理解模板的必要性 3
1.2 編寫你的第一個(gè)模板 6
1.3 理解模板術(shù)語(yǔ) 9
1.4 模板的簡(jiǎn)史 10
1.5 模板的優(yōu)缺點(diǎn) 12
1.6 總結(jié) 12
1.7 問題 13
第2章 模板的基礎(chǔ) 15
2.1 定義函數(shù)模板 15
2.2 定義類模板 18
2.3 定義成員函數(shù)模板 20
2.4 理解模板形參 21
2.4.1 類型模板形參 22
2.4.2 非類型模板形參 23
2.4.3 模板模板形參 28
2.4.4 默認(rèn)模板實(shí)參 30
2.5 理解模板實(shí)例化 32
2.5.1 隱式實(shí)例化 32
2.5.2 顯式實(shí)例化 35
2.6 理解模板特化 39
2.6.1 顯式特化 39
2.6.2 部分特化 43
2.7 定義變量模板 46
2.8 定義別名模板 49
2.9 探索泛型lambda和lambda模板 51
2.10 總結(jié) 57
2.11 問題 57
第3章 變參模板 59
3.1 理解變參模板的必要性 59
3.2 變參函數(shù)模板 61
3.3 形參包 65
3.4 變參類模板 73
3.5 折疊表達(dá)式 79
3.6 變參別名模板 82
3.7 變參變量模板 84
3.8 總結(jié) 84
3.9 問題 85
第Ⅱ部分 高級(jí)模板特性
第4章 高級(jí)模板的概念 89
4. 1 理解名稱綁定和依賴名稱 89
4.1.1 兩階段名稱查找 91
4.1.2 依賴類型名稱 94
4.1.3 依賴模板名稱 96
4.1.4 當(dāng)前實(shí)例化 97
4.2 探索模板遞歸 99
4.3 函數(shù)模板實(shí)參推導(dǎo) 103
4.4 類模板實(shí)參推導(dǎo) 112
4.5 轉(zhuǎn)發(fā)引用 117
4.6 decltype說明符 123
4.7 std::declval類型運(yùn)算符 128
4.8 理解模板中的友元關(guān)系 130
4.9 總結(jié) 135
4.10 問題 135
第5章 類型特征和條件編譯 137
5.1 理解和定義類型特征 137
5.2 探索SFINAE及其目的 141
5.3 使用enable_if類型特征啟用SFINAE 145
5.4 使用 constexpr if 149
5.5 探索標(biāo)準(zhǔn)庫(kù)類型特征 152
5.5.1 查詢類型類別 152
5.5.2 查詢類型屬性 155
5.5.3 查詢支持的操作 157
5.5.4 查詢類型之間的關(guān)系 158
5.5.5 修改const/volatile說明符、引用、指針或符號(hào) 159
5.5.6 各種轉(zhuǎn)換 160
5.6 使用類型特征的實(shí)際例子 163
5.6.1 實(shí)現(xiàn)拷貝算法 163
5.6.2 構(gòu)建同質(zhì)的變參函數(shù)模板 166
5.7 總結(jié) 167
5.8 問題 168
第6章 概念和約束 169
6.1 理解概念的必要性 169
6.2 定義概念 174
6.3 探索requires表達(dá)式 176
6.3.1 簡(jiǎn)單要求 177
6.3.2 類型要求 179
6.3.3 復(fù)合要求 180
6.3.4 嵌套要求 182
6.4 組合約束 183
6.5 了解帶約束模板的順序 187
6.6 約束非模板成員函數(shù) 190
6.7 約束類模板 193
6.8 約束變量模板和模板別名 194
6.9 學(xué)習(xí)更多指定約束的方法 195
6.10 使用概念約束auto形參 196
6.11 探索標(biāo)準(zhǔn)概念庫(kù) 198
6.12 總結(jié) 202
6.13 問題 202
第Ⅲ部分 模板的應(yīng)用
第7章 模式和慣用法 205
7.1 動(dòng)態(tài)多態(tài)和靜態(tài)多態(tài) 205
7.2 奇異遞歸模板模式 208
7.2.1 使用CRTP限制對(duì)象實(shí)例化的次數(shù) 210
7.2.2 使用CRTP添加功能 211
7.2.3 實(shí)現(xiàn)組合設(shè)計(jì)模式 213
7.2.4 標(biāo)準(zhǔn)庫(kù)中的CRTP 217
7.3 混入 220
7.4 類型擦除 225
7.5 標(biāo)簽派發(fā) 231
7.6 表達(dá)式模板 236
7.7 類型列表 243
7.7.1 使用類型列表 245
7.7.2 實(shí)現(xiàn)對(duì)類型列表的操作 247
7.8 總結(jié) 253
7.9 問題 254
第8章 范圍和算法 255
8.1 理解容器、迭代器和算法的設(shè)計(jì) 255
8.2 創(chuàng)建自定義容器和迭代器 262
8.2.1 實(shí)現(xiàn)環(huán)形區(qū)緩沖容器 263
8.2.2 為環(huán)形緩沖區(qū)容器實(shí)現(xiàn)迭代器類型 269
8.3 編寫自定義通用算法 275
8.4 總結(jié) 277
8.5 問題 278
第9章 范圍庫(kù) 279
9.1 從抽象范圍到范圍庫(kù) 279
9.2 理解范圍概念和視圖 281
9.3 理解受約束算法 291
9.4 編寫自己的范圍適配器 294
9.5 總結(jié) 300
9.6 問題 300
附錄A 結(jié)束語(yǔ) 301
以下內(nèi)容可掃描封底二維碼下載
問題答案 303
參考文獻(xiàn) 313