Created
August 8, 2010 21:12
-
-
Save nsf/514544 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <functional> | |
| //------------------------------------------------------------------------- | |
| // Our main callback class, can be binded to function or member function | |
| // of a particular class easily(?) | |
| //------------------------------------------------------------------------- | |
| template <typename Ret, typename ...Args> | |
| struct funcptr_def { | |
| typedef Ret (*type)(Args...); | |
| }; | |
| template <typename Signature> | |
| struct callback; | |
| template <typename Ret, typename ...Args> | |
| struct callback<Ret(Args...)> { | |
| typedef typename funcptr_def<Ret, Args..., void*>::type function_ptr_type; | |
| function_ptr_type fptr; | |
| void *data; | |
| void bind(function_ptr_type fptr, void *data = 0) | |
| { | |
| this->fptr = fptr; | |
| this->data = data; | |
| } | |
| Ret call(Args ...args) | |
| { | |
| return (*fptr)(std::forward<Args>(args)..., data); | |
| } | |
| }; | |
| //------------------------------------------------------------------------- | |
| // Helper binder | |
| //------------------------------------------------------------------------- | |
| template <int ...> struct int_tuple {}; | |
| template <int I, typename IntTuple, typename ...Types> | |
| struct make_indices_impl; | |
| template <int I, int ...Indices, typename T, typename ...Types> | |
| struct make_indices_impl<I, int_tuple<Indices...>, T, Types...> | |
| { | |
| typedef typename make_indices_impl<I+1, int_tuple<Indices..., I>, Types...>::type type; | |
| }; | |
| template <int I, int ...Indices> | |
| struct make_indices_impl<I, int_tuple<Indices...>> { | |
| typedef int_tuple<Indices...> type; | |
| }; | |
| template <typename ...Types> | |
| struct make_indices : make_indices_impl<0, int_tuple<>, Types...> {}; | |
| //------------------------------------------------------------------------- | |
| template <typename T> | |
| void *get_void_ptr(T &&arg) | |
| { | |
| return arg; | |
| } | |
| template <typename T, typename ...Args> | |
| void *get_void_ptr(T &&arg, Args &&...args) | |
| { | |
| return get_void_ptr(std::forward<Args>(args)...); | |
| } | |
| //------------------------------------------------------------------------- | |
| template <typename Ret> | |
| struct callback_helper_impl { | |
| template <typename T, typename MemberFunctionPtr, typename ...Args, int ...Indices> | |
| static Ret callback_run(T *object, MemberFunctionPtr m, const std::tuple<Args&...>& args, int_tuple<Indices...>) | |
| { | |
| return (object->*m)(std::get<Indices>(args)...); | |
| } | |
| }; | |
| template <typename Signature, typename MemberSignature, MemberSignature FunctionPtr> | |
| struct callback_helper; | |
| template <typename Ret, typename ...Args, typename T, typename ...MemArgs, Ret(T::*MemberFunction)(MemArgs...)> | |
| struct callback_helper<Ret(Args...), decltype(MemberFunction), MemberFunction> { | |
| typedef typename make_indices<MemArgs...>::type indices; | |
| static Ret function(Args ...args) | |
| { | |
| T *object = (T*)get_void_ptr(args...); | |
| return callback_helper_impl<Ret>::callback_run(object, MemberFunction, std::tie(args...), indices()); | |
| } | |
| }; | |
| // for convenience (orly?!!?111 omgwtfbbq) | |
| #define WRAP_METHOD(f) decltype(f), f | |
| //------------------------------------------------------------------------- | |
| // Example class | |
| //------------------------------------------------------------------------- | |
| struct dog_t { | |
| void bark(int a, int b) | |
| { | |
| printf("bark! %d %d\n", a, b); | |
| } | |
| }; | |
| //------------------------------------------------------------------------- | |
| // Example function | |
| //------------------------------------------------------------------------- | |
| void say_hello(int a, int b, void *notused) | |
| { | |
| printf("Hello! %d %d\n", a, b); | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| dog_t dog; | |
| callback<void (int, int)> cb; | |
| int i = 1; | |
| // function | |
| cb.bind(say_hello); | |
| cb.call(i, 2); | |
| // member function | |
| cb.bind(callback_helper<void (int, int, void*), WRAP_METHOD(&dog_t::bark)>::function, &dog); | |
| cb.call(i, 2); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment