Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am trying to use a template that takes in an std::function, but the template argument deduction is failing.

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);

The C function-pointer style (funcC) works, but the C++ std::function (funcCxx) doesn't.

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

Any idea what causes this error? Just in case, this is being compiled in clang with C++17, but I don't think it's a compiler error.

like image 362
Nathan29006781 Avatar asked Mar 17 '26 23:03

Nathan29006781


2 Answers

It cannot be deduced because you are not passing a std::function to funcCxx.

Function argument and parameter type must match in template argument deduction. Otherwise deduction fails.

You could let the function take any type instead of constraining it to function pointers or std::function and then you can construct the std::function inside the 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;
}
like image 150
user17732522 Avatar answered Mar 20 '26 13:03

user17732522


The other answer is a good explanation of why you can't use function templates to deduce std::function from a function pointer. But in your comment you said your goal was to constrain the template argument, to only allow types that can be invoked with no arguments.

In c++20, concepts were introduced to make constraining template arguments easier. You can use the invocable concept to only allow types that are callable. If invocable has no arguments, it only accepts types that are callable with no arguments:

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

In c++17, you can use std::is_invocable with std::enable_if_t to accomplish the same thing:

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;
}

In c++14, can use older form of enable_if and this solution

In both cases, you can add using V = decltype(fptr()) inside the function to deduce the return value type.

like image 39
parktomatomi Avatar answered Mar 20 '26 14:03

parktomatomi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!