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?
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
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.