Template parameter - function pointer with variadi

2020-05-28 06:51发布

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条回答
▲ chillily
2楼-- · 2020-05-28 07:34
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.

查看更多
地球回转人心会变
3楼-- · 2020-05-28 07:51

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

查看更多
登录 后发表回答