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

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

我正在尝试使用接受 std::function 的模板,但模板参数推导失败。

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::function (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 and

在这两种情况下,您可以在函数内添加 using V = decltype(fptr()) 以推导出 return 值类型。