#ifndef CALLBACKCONNECTOR_H #define CALLBACKCONNECTOR_H #include <functional> namespace cbc { namespace Details { template <std::size_t Tag, typename T, typename Ret, typename... Args> class FuncMemberWrapper { public: FuncMemberWrapper() = delete; using member_fun_t = Ret (T::*)(Args...); using const_member_fun_t = Ret (T::*)(Args...) const; static auto instantiate(T* t, member_fun_t ptr) { obj = t; member = ptr; return MetaCall; } static auto instantiate(T* t, const_member_fun_t ptr) { obj = t; const_member = ptr; return ConstMetaCall; } private: static auto MetaCall(Args... args) { return (*obj.*member)(args...); } static auto ConstMetaCall(Args... args) { return (*obj.*const_member)(args...); } static T* obj; static member_fun_t member; static const_member_fun_t const_member; }; template <std::size_t Tag, typename T, typename Ret, typename... Args> T* FuncMemberWrapper<Tag, T, Ret, Args...>::obj{}; template <std::size_t Tag, typename T, typename Ret, typename... Args> typename FuncMemberWrapper<Tag, T, Ret, Args...>::member_fun_t FuncMemberWrapper<Tag, T, Ret, Args...>::member{}; template <std::size_t Tag, typename T, typename Ret, typename... Args> typename FuncMemberWrapper<Tag, T, Ret, Args...>::const_member_fun_t FuncMemberWrapper<Tag, T, Ret, Args...>::const_member{}; template <typename Functor, typename Ret, typename... Args> struct FunctorWrapper { public: static std::function<Ret(Args...)> functor; static auto instatiate(Functor fn) { functor = std::move(fn); return MetaCall; } private: static auto MetaCall(Args... args) { return functor(args...); } }; template <typename Functor, typename Ret, typename... Args> std::function<Ret(Args...)> FunctorWrapper<Functor, Ret, Args...>::functor; template <typename Functor, typename Ret, typename T, typename... Args> auto deducer(Functor obj, Ret (T::*)(Args...) const) { return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj)); } template <typename Functor, typename Ret, typename T, typename... Args> auto deducer(Functor obj, Ret (T::*)(Args...)) { return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj)); } template <std::size_t tag, typename T, typename Ret, typename... Args> auto const_instantiate(T* t, Ret (T::*ptr)(Args...) const) { return FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr); } template <std::size_t tag, typename T, typename Func> auto const_instantiate(T* t, Func ptr) { return const_instantiate(t, ptr); } } //end of Details scope template <std::size_t tag = 0, typename T, typename Ret, typename... Args> auto obtain_connector(T* t, Ret (T::*ptr)(Args...)) { return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr); } template <std::size_t tag = 0, typename T, typename Ret, typename... Args> auto obtain_connector(T* t, Ret (T::*ptr)(Args...) const) { return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr); } template <typename Functor> auto obtain_connector(Functor functor) { return Details::deducer(std::move(functor), &Functor::operator()); } } //end of cbc scope #endif // CALLBACKCONNECTOR_H