0
template<typename C, typename Arg>
int foo(C* c, int (C::*func)(Arg), Arg a)
{
  c->*func(a);
}

to call the 'foo', we have to pas both A* and &A::bar,

foo(A*,&A::bar,var);

Is there a way to define the template (e.g as a struct) such that there is no need to pass "A*"? how can I define a template which gets A* from "&A::bar"?

towi_parallelism
  • 1,421
  • 1
  • 16
  • 38

2 Answers2

5

You can't avoid passing the instance if you want to call a non-static method on that instance, unless you don't mind calling it on a temporary, default-constructed instance:

template<typename C, typename Arg>
int call_on_temp(int (C::*func)(Arg), Arg a)
{
    C temp;
    temp.*func(a);
}

or the caller explicitly binds the instance into a functor:

template<typename F, typename Arg>
int call_on_functor(F func, Arg a)
{
    func(a);
}

which makes the call site ugly:

call_on_functor(std::bind(std::mem_fn(&Class::method), instance), arg);

(and you still need the instance, you've just moved it from one place to another).

Note that you can infer the type of A from the function pointer, you just can't infer an instance to call your function on. If you want to call a static method, you don't need the class type at all:

template<typename Arg>
int call_on_static(int (*func)(Arg), Arg a)
{
    func(a);
}
Useless
  • 64,155
  • 6
  • 88
  • 132
1

This should do what you need it to:

template<typename unused>
struct member_function_pointer_type_helper;

template<typename R, typename C>
struct member_function_pointer_type_helper<R C::*> {
    typedef C type;
};

template<typename F>
struct member_function_pointer_type : member_function_pointer_type_helper<typename std::remove_cv<F>::type> {
};

Example:

struct A { void foo() { ... } };


typedef member_function_pointer_type<decltype(&A::foo)>::type a_type; // 'A'

a_type my_a;
my_a.foo(); 

This works by having a specialized template for only member functions, and then simply exports the class part of that member function.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • You forgot the argument types (you specialize for data member pointer, currently). And what's the point? OP already has `C` in `func`'s template parameter list. – jrok Mar 11 '14 at 13:10
  • @jrok the OP wasn't really clear, but I interpreted it as he wanted to induce (and remove) the type of the first parameter, which is either A* or C*. – Richard J. Ross III Mar 11 '14 at 13:13
  • +1 Wow I'm glad I remembered using this weird syntax to define a pointer to function myself; otherwise I'd also wondered why `R C::*` matches a pointer-to-member-function. You might want to add some explanation how it works. – dyp Mar 11 '14 at 13:25
  • I m a bit lost in your code. I thought it would be pretty much straightforward. but If I cannot find another answer I will mark it as an answer. Thanks @RichardJ.RossIII. Agree with dyp. Some explanation might help a lot – towi_parallelism Mar 11 '14 at 13:25
  • @dyp I'm stumped. Why does this match a pointer to member function? – jrok Mar 11 '14 at 13:34
  • Actually guys, I'm not entirely sure why it matches the pointer-to-member. I took the documentation from `std::is_member_function_pointer`, and adapted it into this. So if someone could educate me as well, that would be great. – Richard J. Ross III Mar 11 '14 at 13:40
  • :D Wow it must be really obscure. Here's an example how it works: `using f_t = void(void); using ptr_t = f_t C::*; ptr_t x = &A::foo;` or similarly `using ptr_t = f_t*; void foobar(void); ptr_t x = &foobar;` I.e. you can combine the return type and the argument list. – dyp Mar 11 '14 at 13:43
  • @dyp That's slightly perverse :) TIL. And it just clicked - `R` in `R C::*` can, of course, be a function type when deduced. – jrok Mar 11 '14 at 13:56
  • @jrok Looking into the Standard, I can say *waveshands* itjustworks! (I'm not really into the syntax of declarations..) What I know is that it's an alternative style of declaring a function pointer, where you use a function type (like `void(void)`) to form a function pointer of the form `function_type declarator`. – dyp Mar 11 '14 at 14:00