Here is one simple way, for one argument:
template<typename> struct arg;
template<typename R, typename A>
struct arg<R(*)(A)> { using type = A; };
to be used as (live example)
template<typename T>
T getObjectFromSomewhereElse() { return T{}; }
template <typename F>
void doSomethingWith(F func)
{
using T = typename arg<F>::type;
T obj = getObjectFromSomewhereElse<T>();
func(obj);
}
void f(int x) { std::cout << x << std::endl; }
int main ()
{
doSomethingWith(f); // output 0
}
Here we know that func
will decay to a pointer, that's why we define arg
for a pointer to function.
This only works for functions. For function objects (and lambdas) we need to use a pointer to member operator()
as shown here (thanks Jarod42) and here (thanks OmnipotentEntity).