If you know that the element is a functor, you can simply take its operator() , for example:
#include <iostream> template <unsigned Idx, typename... T> struct pick { static_assert(Idx < sizeof...(T), "cannot index past end of list"); }; template <typename T, typename... TRest> struct pick<0U, T, TRest...> { typedef T result; }; template <unsigned Idx, typename T, typename... TRest> struct pick<Idx, T, TRest...> { typedef typename pick<Idx-1, TRest...>::result result; }; template <typename Func> struct func_traits; template <typename TObj, typename R, typename... TArgs> struct func_traits<R (TObj::*)(TArgs...)> { typedef R result_type; template <unsigned Idx> struct argument { typedef typename pick<Idx, TArgs...>::result type; }; }; template <typename Func, typename Traits = func_traits<Func>, typename R = typename Traits::result_type, typename Arg0 = typename Traits::template argument<0>::type, typename Arg1 = typename Traits::template argument<1>::type > void foo(Func f) { std::cout << __PRETTY_FUNCTION__ << std::endl; }; struct thing { void operator()(long, int*) { } }; int main() { foo(&thing::operator()); }
For me, this program prints:
void foo(Func) [with Func = void (thing::*)(long int, int*), Traits = func_traits<void (thing::*)(long int, int*)>, R = void, Arg0 = long int, Arg1 = int*]
The key point is that Arg0 and Arg1 are long and int* respectively.
source share