Effective C++ 條款48,effective條款48
本節條款:瞭解模板元編程
本節條款是對模板元編程的簡單介紹,讓讀者知道有這麼一種編程方式,更確切的說是一種技術。
那麼,什麼是模板元編程?模板元編程有什麼好處?按照作者的原話就是:
1. TMP可將工作由運行期轉移到編譯期,因而得以實現早期錯誤偵測或者更高的執行效率。
2. TMP可被用來產生“基於政策選擇組合”的客戶定製代碼,也可以用來避免產生對某些特殊類型並不適合的代碼。
說原理容易讓人不知所云,來一段作者的代碼,大家看看。
template <int N>struct Factorial{ enum { value = N * Factorial<N - 1>::value };};template <>struct Factorial<0>{ enum { value = 1 };};int main(){ cout << Factorial<5>::value << endl; }
從上面的代碼我們可以看到我們實現了一個階乘函數。通過調用語句Factorial<5>::value
就可以得出我們需要的結果,這段代碼的推動力就是編譯期間的模板執行個體化過程。收尾工作由特例化模板完成。
如果我們對條款47掌握較好的話,我們就能再次感受模板元編程的優點,可以進行編譯期間的類型識別和編譯期間的函數分配。
我們知道條款47也能通過typeid方式實現,可是typeid方式有的時候卻會出現編譯不通過的錯誤,如下代碼:
template<typename Iter, typename DistT> void advance(IteT& iter,DistT d) { if(typeid(typename std::iterator_traits<IterT>::iterator_category) ==typeid(std::random_access_iterator_tag)) iter+=d; else { if(d>=0) while(d--) ++iter; else while(d++) --iter; } }
如果我們調用語句std::list<int>::iterator iter; advance(iter,10);
執行個體化advance函數,這時候執行個體化過程如下:
void advance(std::list<int>::iterator& iter,int d) { if(typeid(typenamestd::iterator_traits<std::list<int>::iterator>::iterator_category) ==typeid(std::random_access_iterator_tag)) iter+=d;//錯誤 else { if(d>=0) while(d--) ++iter; else while(d++) --iter; } }
上述的語句iter+=d;
將無法通過編譯,原因是list<int>::iterator
的iterator_category類型是bidirectional的,而bidirectional不存在+=運算子的操作,所以編譯不通過。雖然實際運行中if不會內不會執行,但是編譯器卻需要在編譯期間對所有語句進行編譯。
對於TMP編程,我得到的收穫大概就這麼多。