c++ - 在 C++ 中使用模板回调函数

标签 c++ templates callback c2664

我想要一个根据给定回调函数检查特定条件的函数。

考虑这段代码:

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“无法将参数 1 从 bool(int*,int) 转换为 bool(ParamType,int)”

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

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

哪个省略了检查函数的必要声明?

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

最佳答案

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

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)) { ...
}

关于c++ - 在 C++ 中使用模板回调函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18410374/

相关文章:

c++ - C++中模板常量的默认值

c++ - 在没有类型注册或 RTTI 的情况下在 C++ 中实现 type_id(T)

c++ - 让 GDB 显示模板参数的类型

java - 迁移前的 Flyway 回调

javascript - 更新 fullcalendar 事件中传递的变量

javascript - for 循环本身中的 value++

c++ - 删除不同位置的指针会导致不同的行为(崩溃与否)

C++:将 std::string 转换为 UINT64

c++ - C++ 中是否可以使用无状态访问者模式?

c++ - CMake 将不同子目录中的静态库链接到一个静态库中