0

I have this function:

template <typename F>
void doSomethingWith(F func) {

   T obj = getObjectFromSomewhereElse<T>();
   func(obj);
}

I want to deduce the type T from F, where T is the first (and in this case, only) argument to F. Is there a way to do this in C++?

Matt Fichman
  • 5,458
  • 4
  • 39
  • 59
  • Found in [accept-any-kind-of-callable-and-also-know-argument-type](http://stackoverflow.com/questions/21465394/accept-any-kind-of-callable-and-also-know-argument-type/21466644#comment32402978_21466644), http://coliru.stacked-crooked.com/a/00750bf7564ab6d4 may help too. – Jarod42 Apr 16 '14 at 14:18

2 Answers2

1

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).

Community
  • 1
  • 1
iavr
  • 7,547
  • 1
  • 18
  • 53
0

Yes, look at Boost.FunctionTypes. Alternatively, this can be done via template specialization, if you want to do it yourself. I.e. specialize a template for a function type with parameter type A and look at what that is:

template <class T> class parse_first_arg {};
template <class R, class A> class parse_first_arg<R(A)> {typedef A type;};
ltjax
  • 15,837
  • 3
  • 39
  • 62