6

I know I can do this:

template<typename T, typename Ret, typename A1, typename A2, Ret(T::*F)(A1, A2)>
class C{}

But as you can see this A1 and A2 are bit ugly. In fact I don't know the number of arguments. Sounds like a work for variadic templates. Unfortunately I can't do this:

// doesn't work - parameter pack must appear at the end of the template parameter list
template<typename T, typename Ret, typename... Args, Ret(T::*F)(Args...)>
class C{}

Nor this:

template class C;

// doesn't work - wrong syntax
template<typename T, typename F, typename Ret, typename... Args>
class Delegate2<Ret(T::*F)(Args...)>{}

Do I want too much?

2 Answers 2

7

You could do the following:

template<typename T, T> struct C;

template<typename T, typename R, typename ...Args, R (T::*F)(Args...)>
struct C<R (T::*)(Args...), F> {

  R operator()(T &obj, Args &&... args) {
    return (obj.*F)(std::forward<Args>(args)...);
  }

};

and then in your program:

struct A {
  int foo(int i) { return i; }
};

int main() {
  C<int(A::*)(int), &A::foo> c;
  A a;
  std::cout << c(a, 42) << std::endl;
}

Live Demo

Sign up to request clarification or add additional context in comments.

1 Comment

Nice, really nice. It looks like this is what I wanted, thank you, thought I need first to understand how it works. Why do use template<typename T, T>? Why template<typename T> and specialization template<same as before> struct C<R (T::*F)(Args...)> doesn't work?
4
template<class T>struct tag{using type=T;};
template<class Tag>using type=typename Tag::type;

template<class T, class Sig>
struct member_function_pointer;
template<class T, class Sig>
using member_function_pointer_t=type<member_function_pointer<T,Sig>>;

template<class T, class R, class...Args>
struct member_function_pointer<T, R(Args...)>:
  tag<R(T::*)(Args...)>
{};

then

template<class T, class Sig, member_function_pointer_t<T,Sig> mf>
class C{};

should do the trick. If you need access to Args..., you can specialize.

template<class T, class Sig, member_function_pointer_t<T,Sig> mf>
class C;
template<class T, class R, class...Args, member_function_pointer_t<T,R(Args...)> mf>
class C<T, R(Args...), mf> {
};

like that.

2 Comments

Thank you. Looks good and scary. I can barely understand what's going on. Can you please bring some light on your approach? The thing that catch my eye is inheritance. I'm not against it but mixing templates and oop make things much more complicated.
@nikitablack The inheritance is just there so I don't have to type { using type=blah; }, instead I just inherit from : tag<blah> {}. In metaprogramming, I often use template<whatever...> struct some_specialization<a,b,c>:is_really_this_solution<args>{} pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.