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.
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With