11.3 模板與泛型程式設計:編譯期元程式設計(Metaprogramming)的萌芽#
從「容器問題」到「圖靈完備的編譯器」#
C++ 模板(1988–1990)的初衷樸素:寫一個 vector<T>,不必為 int/float/string 各寫一遍。編譯器按需實例化:用到的每個 T 生成一份代碼。
但很快工程師發現模板遠不止於此——模板參數可以是型別、數值、甚至模板本身,而編譯期的模板展開可以包含條件(特化、SFINAE)與遞歸。1994 年 Erwin Unruh 的著名演示:一段模板代碼在編譯錯誤訊息裡打出了質數——編譯器被當成了圖靈完備的直譯器。模板元程式設計(TMP)就此誕生:在編譯期執行的程式,其「輸出」是另一個程式。
回憶第 7 章的同像性:Lisp 用「代碼即資料」在執行期做元程式;C++ 用模板在編譯期做同樣的事。元程式設計的兩條路線——動態(宏/eval)與靜態(模板/泛型)——就此分野。
泛型程式設計的理論化:Stepanov 與 STL#
Alexander Stepanov 把模板從技巧提升為數學方法論。他的核心思想:
演算法應與資料結構解耦——透過「迭代器(iterator)」這個抽象介面溝通。
STL(1994 併入 C++ 標準)的架構:
- 容器(vector、list、map)管理記憶體
- 迭代器是容器與演算法之間的契約(前進、比較、解引用)
- 演算法(sort、find、transform)只依賴迭代器概念
這個「正交分解」來自抽象代數的思想(Stepanov 明言受群論啟發)——數學的「公理化介面」思想直接轉化為軟體架構。C++20 的 Concepts 正式把契約變成語言級概念,完成了這條路線的終點。
TMP 的黃金年代與代價#
1990s–2010s,模板元程式設計成為 C++ 高階工藝的標誌:
| 應用 | 機制 |
|---|---|
| Boost 函式庫 | 模板組合出型別安全的萬能工具 |
| 表達式模板 | A + B + C 不產生中間矩陣——編譯期合成為單次遍歷 |
| 靜態多型 | 模板取代虛函式(CRTP)——零間接成本 |
| 編譯期計算 | constexpr(2011)把 TMP 語言化 |
代價同樣巨大:
- 編譯時間爆炸:模板重代碼(header-only)使大型專案編譯以十分鐘計
- 錯誤訊息如天書:一個型別不匹配產生上百行模板錯誤
- 可讀性斷層:只有少數「模板巫師」能維護核心代碼——抽象能力的不平等分配(同像性的團隊政治問題,C++ 版)
泛型的跨語言譜系#
C++ 模板的成敗成為後繼者的教科書:
| 語言 | 泛型方案 | 對 C++ 模板的修正 |
|---|---|---|
| Java(2004) | 型別擦除泛型 | 執行期只有一份代碼(犧牲效能換簡單) |
| C#(2005) | 執行期泛型(reified) | VM 支援 |
| Haskell | 型別類 | 契約顯式化(Concepts 的先聲) |
| Rust(2015) | trait + 單態化 | 沿 C++ 路線(零成本),契約與錯誤訊息大幅改善 |
| Go(2022) | 才加入泛型 | 刻意晚熟——先驗證「沒有泛型能活多久」(15.1) |
| Swift/TypeScript | 泛型 + 條件型別 | 表達力與可讀性的再平衡 |
有趣的模式:泛型的「要不要、多強、何時」成為每門語言的成人禮難題——表達力與可推論性的恆久張力,本質上是 2 型與 0 型的張力(6.1)在型別層的重演。
編譯期元程式設計的當代形態#
TMP 的思想在 2020s 全面主流化:
- Rust 的宏與 const 泛型、Zig 的 comptime(編譯期與執行期同一語言——TMP 的「最優雅終局」)
- TypeScript 的條件型別(型別層圖靈完備)
- ML 編譯器中的 Kernel 融合(XLA、TorchScript)——模板思想的 AI 版:為每個算子圖生成專用代碼
- LLM 代碼生成(17 章)本質是「統計元程式設計」:模型生成針對具體情境的專用代碼
從宏 → 模板 → comptime → AI 生成,元程式設計的歷史就是不斷回答同一個問題:「程式應該在什麼時候、由誰、用什麼方式被程式化地修改?」——這也是第 16 章的出發點。
小結#
| 概念 | 內容 | 跨語言遺產 |
|---|---|---|
| 模板實例化 | 型別參數化 + 編譯期展開 | C#/Rust/TS 泛型 |
| STL 迭代器抽象 | 演算法與容器解耦 | 各語言的 iterator/trait 體系 |
| TMP | 編譯期圖靈完備 | constexpr、comptime |
| 零成本抽象 | 抽象不留執行期殘跡 | Rust 的核心承諾 |
第三篇結束時,工業界的版圖已定:C 統治系統層、C++ 統治效能層、Java/Smalltalk 血統統治企業層。第四篇,網際網路將把整個版圖掀翻。