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 對等物占用長得多的編譯時間。)
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++ 方法——它的全部工作都在運行時做:
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++ 的下一個版本中將對它提供直接的支持,而且 TR1 已經這樣做了。關于這一主題的書籍也即將開始出版(目前,C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond 已經出版——譯者注),而 web 上的 TMP 信息也正在保持增長。TMP 也許永遠不會成為主流,但是對于某些程序員——非凡是庫開發者——它幾乎必然會成為主料。