Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;_C++_Templates_Callback_C2664 - Fatal编程技术网

C++ 在C++;

C++ 在C++;,c++,templates,callback,c2664,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, co

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

考虑到这一准则:

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();
}
(显示问题的所有构造示例)

编译器将无法获得该值,并抛出错误C2664“无法在bool(ParamType,int)中从bool(int*,int)转换参数1”

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

template< typename ParamType, Check >
void DoSmth(Check isGood, const ParamType param)
模板
无效DoSmth(检查是否良好,常数参数类型参数)
检查功能的必要声明是什么


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

使用functor模板可以解决您的问题:

template< typename Functor, typename ParamType >
void DoSmth(Functor isGood, const ParamType param){
   //...
   if(isGood(param, some_int_calculated_here)) doSmthElse();
}
template
void DoSmth(函子isGood,常量ParamType param){
//...
如果(isGood(参数,此处计算的部分))doSmthElse();
}

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

问题在于模板函数的第一个参数是不可推断的:

template< typename ParamType >
void DoSmth(typename IsGood<ParamType>::Check isGood, const ParamType param)
//          ^        ^^^^^^^^^^^^^^^^^^^^^^^^
//          missing  nested type! not deducible!
模板
void DoSmth(typename IsGood::Check IsGood,const ParamType param)
//          ^        ^^^^^^^^^^^^^^^^^^^^^^^^
//缺少嵌套类型!不可推断!
简单的选项是就地展开签名(C++03,C++11):

模板
void DoSmth(void(*isGood)(ParamType,int),const ParamType param)
//注意:删除的“const”无论如何都会被编译器删除
或者,如果您有C++11,您可以用模板别名替换
IsGood::Check

template <typename T>
using IsGood = void (*)(T,int);
template< typename ParamType >
void DoSmth(IsGood<ParamType> isGood, const ParamType param)
模板
使用IsGood=void(*)(T,int);
模板
void DoSmth(IsGood IsGood,const ParamType param)
或者重构代码,采用一个函子,使其更灵活、更简单、更高效,因为编译器更容易内联调用:

template <typename P, typename T>
void DoSmth(P predicate, T param) {
   if (predicate(param,somethingelse)) { ...
}
模板
void DoSmth(P谓词,T参数){
如果(谓词(param,somethingelse)){。。。
}

我在回答之前没有看到最后一行。为什么使用表示函子的模板参数不是一个选项?对我来说很有效:(在添加/删除
typename后,如果需要)@user2093113
checkEqualFloat
不起作用。@mfontani确实起作用,但这是因为问题中指定的
checkEqualFloat
IsGood::Check
函数签名不匹配。更正签名以
int
作为第二个参数起作用:。@user2093113:您的代码正在工作。I just忘记了一件事:ParamTypes是作为指针提供的。我更新了这个问题。很抱歉。我认为它应该是一样的。但是它可以在IsGood中匹配指针并使用“DoSmth(IsGood::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)) { ...
}