6

I have a pointer to the method:

struct A { int method() { return 0; } };
auto fn = &A::method;

I can get a return type by std::result_of, but how I can get from fn the class owner of the method?

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
user2427770
  • 130
  • 9
  • You can't, there's no such trait in the standard. A compiler would know it, so it should be possible, but there's simply no way to get that information. – Some programmer dude Feb 11 '17 at 11:31
  • 4
    template ClassType foo(ReturnType (ClassType::*)(Args...)); should work – felix Feb 11 '17 at 11:40
  • 1
    @felix You should write that as an answer. – nwp Feb 11 '17 at 11:43
  • edited on my phone. too hard to provide a well formed answer.. : | – felix Feb 11 '17 at 11:46
  • Take a look to [this question](http://stackoverflow.com/questions/35043772/weird-pointer-to-member-function-syntax) related to [p0172r0 paper](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0172r0.html); it mentions a *weird* way to split class type from pointer-to-member function. – PaperBirdMaster Feb 13 '17 at 09:27

3 Answers3

6

You can match it using class-template-specialization:

//Primary template
template<typename T> struct ClassOf {};

//Thanks T.C for suggesting leaving out the funtion /^argument
template<typename Return, typename Class>
struct ClassOf<Return (Class::*)>{   using type = Class;    };

//An alias
template< typename T> using ClassOf_t = typename ClassOf<T>::type;

Hence given:

struct A { int method() { return 0; } };
auto fn = &A::method;

We can retrieve the class like:

ClassOf_t<decltype(fn)> a;

Full example Here.

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
4

Try this:

template<class T>
struct MethodInfo;

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...)> //method pointer
{
    typedef C ClassType;
    typedef R ReturnType;
    typedef std::tuple<A...> ArgsTuple;
};

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) const> : MethodInfo<R(C::*)(A...)> {}; //const method pointer

template<class C, class R, class... A>
struct MethodInfo<R(C::*)(A...) volatile> : MethodInfo<R(C::*)(A...)> {}; //volatile method pointer
The Techel
  • 918
  • 8
  • 13
0

Boost callable traits answer, I like it better than shorter answers here since it is a bit more readable to me, but opinions might differ...

#include<string>
#include<type_traits>
#include<tuple>
#include <boost/callable_traits/args.hpp>

struct S{
    int val=46;
    int get(){
        return val;
    }
    void method(const std::string ){
    }
};

int main(){
    using Ts1 = boost::callable_traits::args_t<decltype(&S::val)>;
    using Ts2 = boost::callable_traits::args_t<decltype(&S::get)>;
    using Ts3 = boost::callable_traits::args_t<decltype(&S::method)>;
    std::remove_cvref_t<std::tuple_element<0,Ts1>::type> s1;
    s1.val++;
    std::remove_cvref_t<std::tuple_element<0,Ts2>::type> s2;
    s2.val++;
    std::remove_cvref_t<std::tuple_element<0,Ts3>::type> s3;
    s3.val++;
}

s1, s2, s3 are all of type S.

Obviously you need to do the logic only once, I did it 3 times to show it works fine for pointer to member, pointer to function that takes 0 arguments, pointer to function that takes 1 argument.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277