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?
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.
Variadic functions are functions (e.g. printf) which take a variable number of arguments.
Function pointers can be useful when you want to create callback mechanism, and need to pass address of a function to another function. They can also be useful when you want to store an array of functions, to call dynamically for example.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With