3

I'm looking to extend the functionality described here but for member functions, what would be the syntax in this case?

Also, the (*) in the template definition, is that de-referencing the function pointer so the compiler can deduce the template arguments?

Would appreciate any input!

Thanks

template <class F> struct ArgType;

template <class R, class T> 
struct ArgType<R(*)(T)> {
  typedef T type;
}; 

void f(int) {}

#include <type_traits>
#include <iostream>

int main() {

  // To prove
  std::cout << std::is_same< ArgType<decltype(&f)>::type, int >::value << '\n';

  // To use
  ArgType<decltype(&f)>::type a;
}
Community
  • 1
  • 1
  • The `*` in the template definition is simply part of the syntax for a function pointer. – phantom Apr 27 '15 at 21:29
  • This is a function pointer, and you need a member function pointer, which is a `R(T::*)(Args...)` – chris Apr 27 '15 at 21:30
  • Decomposing a member function type is usually done in something called a "member function (type) trait". There are several implementations already on StackOverflow; boost also contains one. – dyp Apr 27 '15 at 21:31

1 Answers1

4

Pointer-to-members look like Ret (Cls::*)(Args...) [cv-qualifiers] [ref-qualifiers]. So you can extend your class to deduce the first type thusly:

template <class F> struct ArgType;

template <typename Ret, typename Cls, typename T, typename... Args>
struct ArgType<Ret (Cls::*)(T, Args...)> {
    using type = T;
};

Note that you can make this more generic by write a metafunction that gives you the nth argument:

template <typename Ret, typename Cls, typename... Args>
struct ArgType<Ret (Cls::*)(Args...)> {
    
    template <size_t N>
    struct get_arg {
        using type = typename std::tuple_element<N,
                        std::tuple<Args...>>::type;
    };
};

So ArgType<F>::arg<0>::type would be the type you seek.

Barry
  • 286,269
  • 29
  • 621
  • 977