原文:http://blogs.msdn.com/xiangfan/archive/2009/02/09/c-template-trick-detecting-the-existence-of-class-member-at-compile-time.aspx
c++0x提供了豐富的type trait用於generic程式設計。但是,其中並沒有探測類成員的type trait。不借助編譯器的幫助,要實現這個type trait是很困難的。這裡我們對需求進行適當的修改:探測類中是否存在指定名稱和型別的成員。
在c++中,函式過載是最常見的實現type trait的方法。但是,函式過載是基於型別的。預設引數和訪問許可權都在函式過載之後進行。這裡我們希望探測指定的成員是否存在,所以需要找到一種將成員轉換為型別的方法。幸運的是,模板支援非型別的引數。下面展示了基於這一想法的實現:
namespace van ;
template
struct memberhelperclass;
template
small memberhelper_f(memberhelperclass*);
template
big memberhelper_f(...);
} template
struct has_member_f;};
}}struct a
;struct b
;#include
using
namespace std;
int main()//
template
/struct has_member_##name/
;/};/}/}
這個type trait的乙個用處是簡化dispatcher。比如,為了提供程式的效能,我們需要針對不同的平台提供不同的實現。利用成員探測的type trait,我們可以讓dispatch完全自動化。
首先,我們將不同的實現放在同乙個輔助類裡
struct memorycopyhelper
static
void mmx(const
void *lpdest, void *lpsrc, size_t n){}
};其次,我們建立乙個函式陣列用於存放每個實現的位址。如果某個平台沒有對應的優化實現,我們將採用預設的版本(假定預設版本總是存在)
definehasmember(default)
definehasmember(mmx)
definehasmember(sse2)
#define defineselectstaticmember(membername)/
template
/struct select_member_##membername;/
template
/struct select_member_##membernametrue> ;/
template
/struct select_member_##membernamefalse> ;/
template
/const funtype select_member_##membernametrue>::value=&t::membername;/
template
/const funtype select_member_##membernamefalse>::value=&t::default;
defineselectstaticmember(default)
defineselectstaticmember(mmx)
defineselectstaticmember(sse2)
memorycopyhelper::functiontype gdispatcharray_memorycopy=;
然後你就可以將精力集中在實現上。你可以在以後向輔助類中新增其它平台的優化實現版本,函式陣列會自動更新(注:上面的陣列是在程式進入main之前動態初始化的)
ps:上面的**在vc8、vc9和gcc 3.4.5上測試通過。一些老的編譯器可能無法編譯通過。
c 模板類如何定義模板成員函式
最近跟網上乙個解決乙個模板問題 其實他在用g 編譯器寫模板定義成員函式,我在vs 05的c 編譯器上寫,然後我測試模板的結果是 特例模板不可以在類外定義,不管是在標頭檔案還是cpp檔案都要報錯,然後跟他說讓他寫在類中 當時不知道他在用g 編譯器 於是悲劇的問題出來了 他那個老是報沒在未命名空間類域中...
C 類模板的成員函式模板寫法
這幾天本來想將lua tinker移植到linux上去的,但是由於vc中的模板寫法與gcc中的模板寫法有些不同之處,比如下面一段 struct pop template static char invoke lua state l,int index template static const ch...
C 中模板類的靜態成員
目錄 c 中模板類的靜態成員 為什麼需要模板類的靜態成員?示例 模板類的靜態成員和普通類,普通函式的靜態成員一樣,我們想在函式呼叫後留些資訊,而且這些資訊隨著函式呼叫的次數發生改變,也就說函式或者類物件執行完後,並沒有完全消除而是留下了一下蹤跡,比如 函式呼叫次數,物件宣告次數 等等。以類為例,這些...