跳轉到

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)只依賴迭代器概念
\[\text{演算法} \times \text{容器} \;\rightarrow\; M \times N \text{ 種組合只需 } M + N \text{ 份代碼}\]

這個「正交分解」來自抽象代數的思想(Stepanov 明言受群論啟發)——數學的「公理化介面」思想直接轉化為軟體架構。C++20 的 Concepts 正式把契約變成語言級概念,完成了這條路線的終點。

TMP 的黃金年代與代價#

1990s–2010s,模板元程式設計成為 C++ 高階工藝的標誌:

應用 機制
Boost 函式庫 模板組合出型別安全的萬能工具
表達式模板 A + B + C 不產生中間矩陣——編譯期合成為單次遍歷
靜態多型 模板取代虛函式(CRTP)——零間接成本
編譯期計算 constexpr(2011)把 TMP 語言化

代價同樣巨大:

  1. 編譯時間爆炸:模板重代碼(header-only)使大型專案編譯以十分鐘計
  2. 錯誤訊息如天書:一個型別不匹配產生上百行模板錯誤
  3. 可讀性斷層:只有少數「模板巫師」能維護核心代碼——抽象能力的不平等分配(同像性的團隊政治問題,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 血統統治企業層。第四篇,網際網路將把整個版圖掀翻。


下一節:12.1 縮排即語法