5

我想要一个基于给定回调函数检查某些条件的函数。

考虑这段代码:

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(ParamType,int) 中从 bool(int*,int) 转换参数 1 是不可能的”

我有一个不使用的解决方案

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

哪个省略了检查功能的必要声明?

最好的解决方案是在函数本身中获取 IsGood() 标头。

4

2 回答 2

4

问题是您的模板函数的第一个参数是不可推导的:

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)) { ...
}
于 2013-08-23T20:30:01.580 回答
3

使用仿函数模板将解决您的问题:

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

现在,您可以使用任何具有兼容签名的函数或仿函数对象(不一定以 aParamType和 anint作为参数)。否则,您将需要使用具有该确切签名的函数。

于 2013-08-23T19:25:44.283 回答