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.編譯器是通過尋找最合適的匹配選項來匹配選擇實例化的類型