工作中遇到一個問題,我有一個容器,裝著各式各樣的對象的指針,需要把擁有dump方法的指針內容dump出去,而對于沒有dump方法的對象,直接忽略。
首先想到的是給每個對象提供一個查詢操作,從而得知是否擁有dump方法。顯然這個方法不能讓人滿意,需要更改大量的class實現。C++如果我能自動判斷某個類型是否擁有某方法,這個問題可以完美的解決,因為是否含有某方法編譯期已經確定了,所以是有可能通過一些技巧來實現這個功能的。
查閱了大量的模板偏特化,匹配失敗不是錯誤,終于找到了Mr.Right:
廢話不多說,貼代碼:
檢測是否有定義
void hello():
點擊(此處)折疊或打開
template<typename T>
struct has_hello{
template<typename U,
void (U::*)()>
struct HELPS;
template<typename U>
static char Test(HELPS<U, &U::hello>*);
template<typename U>
static int Test(

);
const static bool Has =
sizeof(Test<T>(0)) ==
sizeof(
char);
}
測試:
點擊(此處)折疊或打開
struct A
{
void hello(){
cout<<"A is Hello."<<endl;
}
int x;
};
int main()
{
cout<<"A has hello? "<<has_hello<A>::Has<<endl;
}
has_hello 能編譯通過,而且能工作!!!
解釋:
template<typename U>
static int Test(

); 能匹配所有的類型U
template<typename U,
void (U::*)()>
struct HELPS; 當Type U有hello,且hello的類型為
void (U::*)()時,模板HELPS<U, &U::hello>能正確匹配,否則模板無法匹配
Test<T>(0) 優先匹配 HELPS<U, &U::hello> 因為template<typename U>
static char Test(HELPS<U, &U::hello>*) 是一個特化
sizeof操作符不需要計算表達式的值,是一個編譯期的操作,定義指針類型可以只有聲明沒有定義
所以HELPS和Test都不需要實現,僅有聲明就可以通過編譯
巧妙的探測了自定義類型A是否含有void U::hello() 方法。
轉自:http:
//blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=17286628&id=4643663