You can deduce T
if the object passed into the function actually has type std::function<void(T)>
. If the type you pass in is a lambda, then you'll have to deduce it from the type of the lambda's function call operator, like so:
template <class Callable, class Arg, class T>
void f_helper(Callable callable, Ret (Callable::*)(T)) {
// do something with T
}
template <class Callable>
void f(Callable callable) {
f_helper(callable, &callable::operator());
}
Actually, in reality it is a bit more annoying than this, because you need at least two overloads for f_helper
, according to whether the lambda is declared mutable (which determines whether operator()
is const
), and in C++17 you also need to double the number of overloads again according to whether the lambda is noexcept
.
The standard library sidesteps issues like this by not attempting to extract the argument type from the callables you pass to algorithms such as std::sort
. It just accepts an arbitrary callable type and then tries to call it.