Chris Stathis Chris Stathis - 5 months ago 33
C++ Question

Passing a function with templated parameters as an argument, with function pointers vs. std::function

So I have some generic class with two functions that take functions as parameters. One takes a function pointer and one takes a std::function. Both have a template parameter.

#include <functional>
#include <memory>

namespace {
void example(const std::shared_ptr<const int>&) {}

class Generic {
Generic() {}
virtual ~Generic() {}
template <typename Targ>
void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) {}

template <typename Targ>
void doWork2(void(*function)(const std::shared_ptr<const Targ>&)) {}

class Special : public Generic {
Special() {
//doWork(&example); // Fail!
doWork<int>(&example); // OK!
std::function<void(const std::shared_ptr<const int>&)> func = &example;
doWork(func); // OK!
doWork2(&example); // OK!

int main(int argc, char** argv) {
Special special;
return 0;

With the function pointer it compiles, but with the std::function it does not. Why does template deduction fail here?

Clang reports:

example.cpp:27:9: error: no matching member function for call to 'doWork'
example.cpp:14:10: note: candidate template ignored: could not match 'function<void (const shared_ptr<const type-parameter-0-0> &)>' against 'void (*)(const std::shared_ptr<const int> &)'
void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) {
1 error generated.


Template argument deduction does not work like that.

Template argument deduction is a pattern match. Is example an object of type std::function<void(const std::shared_ptr<const Targ>&)> for some type Targ?

Not convertible-to, but actually an object of that type already?

No, it is not.

It is, however, already a function pointer (using the implicit decay rules).

There is a C++17 feature that involve deducing template arguments from constructor types; std::function may or may not be instrumented to learn its own type from a function pointer when C++17 or C++20 comes out in this situation. I lack expertise in C++17 to be certain.