2013-08-23 20 views
2

我想有一個函數根據給定的回調函數檢查某些條件。在C++中使用模板回調函數

認爲這代碼:

class Foo{ 
template <class ParamType> 
struct IsGood 
{ 
    typedef bool (*Check)(typename const ParamType*, int other); 
}; 
template< typename ParamType > 
void DoSmth(IsGood<ParamType>::Check isGood, const ParamType* param){ 
    //... 
    if(isGood(param, some_int_calculated_here)) doSmthElse(); 
} 

我想是把它稱爲:

bool checkEqualInt(int* i, int j){return *i==j;} 
bool checkEqualFloat(float* i, float j){return *i==j;} 

DoSmth(checkEqualInt, &i); 
DoSmth(checkEqualFloat, &i_float); 

(所有構造例子來說明這個問題)

編譯器不會得到並拋出錯誤C2664「將bool(int *,int)中的參數1轉換爲bool(ParamType,int)不可能」

我有沒有使用

template< typename ParamType, Check > 
void DoSmth(Check isGood, const ParamType param) 

其中ommits的檢查功能的必要聲明的解決方案?

最好的解決方案是獲取函數本身的IsGood()頭。

+0

我沒有看到最後一行纔回答。爲什麼使用代表仿函數的模板參數不是一個選項? – mfontanini

+1

適用於我:http://ideone.com/czNr1e(在必要時添加/刪除'typename'後)。 – user2093113

+0

@ user2093113'checkEqualFloat'雖然不起作用。 – mfontanini

回答

2

使用仿函數模板將解決你的問題:

template< typename Functor, typename ParamType > 
void DoSmth(Functor isGood, const ParamType param){ 
    //... 
    if(isGood(param, some_int_calculated_here)) doSmthElse(); 
} 

現在你可以使用具有(即需要ParamTypeint作爲參數不一定是一個)兼容簽名的任何函數或仿函數對象。否則,您將需要使用具有該確切簽名的函數。

+0

如上所述,我想避免functor在函數頭本身指定函數簽名 – Flamefire

0

的問題是,你的模板函數的第一個參數是不能推斷出:

template< typename ParamType > 
void DoSmth(typename IsGood<ParamType>::Check isGood, const ParamType param) 
//  ^  ^^^^^^^^^^^^^^^^^^^^^^^^ 
//   missing nested type! not deducible! 

簡單的選項是擴大地方簽名(C++ 03,C++ 11):

template< typename ParamType > 
void DoSmth(void (*isGood)(ParamType,int), const ParamType param) 
// note: dropped 'const' that will be dropped anyway by the compiler 

或者,如果你有C++ 11,你可以通過一個模板別名替代IsGood<ParamType>::Check

template <typename T> 
using IsGood = void (*)(T,int); 
template< typename ParamType > 
void DoSmth(IsGood<ParamType> isGood, const ParamType param) 

或可選擇地重構代碼採取仿函數,這將使它更加靈活,簡單和高效可能以後還會有更容易爲編譯器內聯電話:

template <typename P, typename T> 
void DoSmth(P predicate, T param) { 
    if (predicate(param,somethingelse)) { ... 
}