Thanks for all the answers.
I found a good example from section 14.8.2.5-21 of the standard:
template<class> struct X { }; template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { }; template<class ... Types> struct Y { }; template<class T, class ... Types> struct Y<T, Types& ...> { }; template<class ... Types> int f(void (*)(Types ...)); void g(int, float);
It says that with the help of template specialization, we can analyze the parameters of a function type template (amazing)! The following is a dirty / simple example of how std :: function works:
template<class T> struct Function { }; template<class T, class Obj, class... Args> struct Function<T(Obj*, Args...)> // Parsing the function type { enum FuncType { FuncTypeFunc, FuncTypeMemFunc }; union FuncPtr { T(*func)(Obj*, Args...); T(Obj::*mem_func)(Args...); }; FuncType m_flag; FuncPtr m_func_ptr; Function(T(*func)(Obj*, Args...))
Using:
#include <iostream> struct Funny { void done(int i, int j) { std::cout << "Member Function: " << i << ", " << j << std::endl; } }; void done(Funny* funny, int i, int j) { std::cout << "Function: " << i << ", " << j << std::endl; } int main(int argc, char** argv) { Funny funny; Function<void(Funny*, int, int)> f = &Funny::done; // void(Funny::*)(int, int) Function<void(Funny*, int, int)> g = &done; // void(*)(Funny*, int, int) f.play(&funny, 5, 10); // void(Funny::*)(int, int) g.play(&funny, 5, 10); // void(*)(Funny*, int, int) return 0; }
Edit: Thanks to Tomek for his good allusion to union s, the above example has changed to hold a pointer to a member / non-member function in one (not two) variable.
Edit: Martin York is right, the switch statement was not a good idea in the above example, so I completely changed the example to work better:
template<class T> class Function { }; template<class Res, class Obj, class... ArgTypes> class Function<Res (Obj*, ArgTypes...)> // Parsing the function type { union Pointers // An union to hold different kind of pointers { Res (*func)(Obj*, ArgTypes...); // void (*)(Funny*, int) Res (Obj::*mem_func)(ArgTypes...); // void (Funny::*)(int) }; typedef Res Callback(Pointers&, Obj&, ArgTypes...); Pointers ptrs; Callback* callback; static Res call_func(Pointers& ptrs, Obj& obj, ArgTypes... args) { return (*ptrs.func)(&obj, args...); // void (*)(Funny*, int) } static Res call_mem_func(Pointers& ptrs, Obj& obj, ArgTypes... args) { return (obj.*(ptrs.mem_func))(args...); // void (Funny::*)(int) } public: Function() : callback(0) { } Function(Res (*func)(Obj*, ArgTypes...)) // void (*)(Funny*, int) { ptrs.func = func; callback = &call_func; } Function(Res (Obj::*mem_func)(ArgTypes...)) // void (Funny::*)(int) { ptrs.mem_func = mem_func; callback = &call_mem_func; } Function(const Function& function) { ptrs = function.ptrs; callback = function.callback; } Function& operator=(const Function& function) { ptrs = function.ptrs; callback = function.callback; return *this; } Res operator()(Obj& obj, ArgTypes... args) { if(callback == 0) throw 0; // throw an exception return (*callback)(ptrs, obj, args...); } };
Using:
#include <iostream> struct Funny { void print(int i) { std::cout << "void (Funny::*)(int): " << i << std::endl; } }; void print(Funny* funny, int i) { std::cout << "void (*)(Funny*, int): " << i << std::endl; } int main(int argc, char** argv) { Funny funny; Function<void(Funny*, int)> wmw; wmw = &Funny::print; // void (Funny::*)(int) wmw(funny, 10); // void (Funny::*)(int) wmw = &print; // void (*)(Funny*, int) wmw(funny, 8); // void (*)(Funny*, int) return 0; }