系列第十講,冒號老師引領學生跨越「寫程式」的邊界,進入「寫寫程式的程式」——元編程(Metaprogramming)的殿堂。從 C++ 模板元編程的編譯期運算,到 Lex/Yacc 的語法導向生成,再到 DSL、生成式編程、自我修改代碼,揭示「程式的程式」如何實現智能繁衍。
Meta- 意為「超級」、「元」、「關於……的……」。
template <int N>
struct factorial {
enum { value = N * factorial<N - 1>::value };
};
template <> // 特化:遞歸終止
struct factorial<0> {
enum { value = 1 };
};
int main() {
std::cout << factorial<5>::value << std::endl; // 輸出 120,編譯期已計算完成
}
關鍵差異:factorial<5>::value 在編譯期展開為常數 120,零執行期開銷。這不是函式呼叫,而是編譯器對模板的遞歸實例化與常數摺疊。
問題:用戶文檔格式多變、頻繁調整,手寫解析器維護成本極高(寫碼、除錯、重編譯、重部署)。
元編程解法:
這正是 Lex(詞法分析器生成器) 與 Yacc(語法分析器生成器) 的核心價值:根據文法規範生成解析器。更進一步,規範可包含動態指令,演變為領域特定語言(DSL),甚至結合圖形介面,讓業務主管「點點滑鼠」即可變更業務流程——這是語言導向編程(LOP)的雛形。
| 範疇 | 代表技術 | 核心能力 |
|---|---|---|
| 編譯期運算 | C++ Template Metaprogramming, Rust const generics | 類型運算、常數摺疊、靜態斷言 |
| 原始碼生成 | Lex/Yacc, ANTLR, Protocol Buffers, Thrift, Swagger Codegen | 從規格生成解析器/序列化/客戶端 SDK |
| 生成式編程 (GP) | 模板引擎, 程式碼生成器, MDA 工具 | 批量產出樣板碼、架構骨架 |
| 運行時元編程 | Lisp Macro, Ruby/JS eval, Java Reflection/ASM, C# Roslyn | 動態定義類/方法、修改行為、AOP 織入 |
| 編譯器本身 | GCC, LLVM, javac, JSP 引擎 | 將高階語言轉譯為機器碼/位元組碼的程式 |