1.編譯器斷言
技巧大致跟後面的一樣,都是利用偏特化,但是在C++ 0X裡面已經有static_assert,所以感覺這東西也沒什麼用處了,更多的只是開闊眼界 2.偏特化 就是專門對一個類型去進行特殊的處理,畢竟template會給生成所有的類型相同的操作,但是有時候我們需要對特定的幾個類型去處理,於是就有了特化和偏特化 3.局部類 一直被忽略的C++的語法,可以直接在類或者函數裡面定義類,不過一直被忽視就對了,感覺這個還是挺有意思的 4.常數映射為型別: template <int v> struct Int2Type { enum { value = v; } } 這樣的話,每次用不同的數字去實例化Int2Type,都是不同的類型 書中舉了個反例1 <class T,bool flag> 2 class myclass 3 { 4 void DoSomething () 5 { 6 if(flag ) 7 { 8 T *new_obj = p_old_obj-> clone(); 9 } 10 else 11 { 12 T *new_obj = new T(p_olb_obj ); 13 } 14 } 15 };
上面的程序有兩個問題 1.如果T的類型把復制構造函數聲明為private或者protect,則編譯錯誤 2.如果p_old_obj沒事實現clone,則編譯錯誤 我們可以這樣改造下面的程序:
template <class T, bool isPolymorphic > class NiftyContainer { private: void DoSomething (T * pobj,int2type <true>) { T *pNewObj = pobj-> clone(); } void DoSomething (T * pobj,int2type <false>) { T *pNewObj = new T(pobj ); } public: void DoSomething (T * pobj) { DoSomething(pobj ,int2type< isPolymorhpic>()); } };
這樣,只要你的程序有實現clone或者將復制構造函數設置為public,只要符合其中一個條件,就可以編譯通過,而且選擇什麼動作是編譯的時候就決定的 之所以只要實現clone或者public了復制構造函數就可以通過,是因為編譯器不會去編譯一個未用到的類成員函數 5.型別對型別的映射 在我們編程的時候,我們經常需要創建一個函數,用以產生一個新對象
template <class T, class U > T *create (const U &arg ) { return new T( arg); }
那如果現在需要構造一個widget對象,但是這個對象需要-1作為構造參數,怎麼辦?? 我們可以利用type2type來讓編譯器去選擇我們要使用哪個模板函數
template <class T, class U > T *create (const U &arg ,type2type< T>) { return new T( arg); } template <class U> widgets *create (const & arg,type2type <widgets>) { return new widgets( arg,-1); }
6,型別選擇 有了前面的基礎,看到後面的幾個也就輕松,原理跟3(型別映射型別差不多) 其實就是利用函數的偏特化機制
template <bool flag, class T ,class U> struct select { typedef T result; }; template <class T, class U > struct select <false, T,U > { typedef U result; };
我們可以根據flag來在編譯的時候就決定是要使用T還是使用U類型,不過這本書中的例子是用來選擇是使用指針還是使用普通的類型,感覺這個例子沒有traits好用 7.在編譯期的時候確定一個類型是否可以轉換成為另外一個類型(這樣說感覺不怎麼准確,更准確地說類型是否會隱式轉換為另外一個類型)
template <class T, class U > class conver { typedef char small; class big { char dummy [2]; }; static small test( U); static big test(...); static T makeT(); public: enum { exists = sizeof ( test( makeT() ) ) == sizeof(small ) }; };
這樣,我們在寫程序的時候,可以直接這樣來判斷一個類是否可以轉換成另外一個類 算起來這個算是我覺得比較有趣的模板技巧了 1.實際上smalltest和bigtest還有makeT都沒有實例化出來,因為sizeof並不會有實例化操作,所以即使沒有定義函數,依然通過編譯 2.多聲明了一個makeT函數是因為一些類會把構造函數聲明為私有的,如果不使用makeT,那麼將無法調用T() 3.模板會尋找最佳匹配條件,也就是說,如果我們再多聲明一個類型Z,把static big test(...)改成static big test(Z),那麼在我們程序編譯的時候,即使兩個類型能夠互相轉換,比如int和size_t,那麼編譯器將會去調用test(Z),這樣將無法看出兩個類是否可以互相轉換,反之,如果test是(...)這樣聲明的,那麼編譯器會認為test(U)比test(...)匹配,於是就去使用test(U)函數 8.type_info的外覆類 這個倒沒什麼,無非就是type_info無法復制,所以重新寫了一個類包裝下 9.定義Nulltype和emptyType復制類 也沒什麼好說的 10.traits 在前面的文章已經說過了 http://www.cnblogs.com/linyilong3/p/3379433.html. 總的來說,要理解這些技巧,需要理解幾點: 1.模板的特化 2.編譯器是通過尋找最合適的匹配選項來匹配選擇實例化的類型