候选模板已忽略:无法将'function<type-parameter-0-0 ()>'与'double (*)()'匹配

candidate template ignored: could not match 'function<type-parameter-0-0 ()>' against 'double (*)()'

本文关键字:type-parameter-0-0 lt gt 匹配 double function 候选      更新时间:2024-09-28

我试图使用一个接受std::函数的模板,但模板参数推导失败。

double foo(){
return 2.3;
}
template <typename V>
void funcC (V (*fptr)()){
std::cout << "C function's value is"" << fptr() << '"' << std::endl;
}
template <typename V>
void funcCxx (std::function<V()> fptr){
std::cout << "C++ function's value is"" << fptr() << '"' << std::endl;
}
funcC (foo);
funcCxx (foo);

C函数指针样式(funcC(有效,但C++std::函数(funcCxx

我得到这个编译器错误candidate template ignored: could not match 'function<type-parameter-0-0 ()>' against 'double (*)()'

知道是什么导致了这个错误吗?以防万一,这是用C++17在clang中编译的,但我不认为这是编译器错误。

无法推导,因为您没有将std::function传递给funcCxx

在模板参数推导中,函数参数和参数类型必须匹配。否则扣款失败。

您可以让函数采用任何类型,而不是将其约束为函数指针或std::function,然后您可以在函数内部构造std::function

template <typename V>
void funcCxx (V&& v){
auto f = std::function(std::forward<V>(v));
std::cout << "C++ function's value is"" << f() << '"' << std::endl;
}

另一个答案很好地解释了为什么不能使用函数模板从函数指针推导std::function。但在你的评论中,你说你的目标是约束模板参数,只允许在没有参数的情况下调用类型。

在c++20中,引入了一些概念,使约束模板参数变得更容易。您可以使用invocable概念来只允许可调用的类型。如果invocable没有参数,它只接受不带参数的可调用类型:

void funcCxx20(std::invocable auto fptr) {
std::cout << "C++20 function's value is"" << fptr() << '"' << std::endl;
}

在c++17中,您可以使用std::is_invocablestd::enable_if_t来完成相同的事情:

template <typename F>
std::enable_if_t<std::is_invocable_v<F>, void> funcCxx(F&& fptr) {
std::cout << "C++ function's value is"" << fptr() << '"' << std::endl;
}

在c++14中,可以使用较旧形式的enable_if和此解决方案

在这两种情况下,都可以在函数中添加using V = decltype(fptr())来推断返回值类型。