Skip to content

Instantly share code, notes, and snippets.

@airekans
Created October 10, 2015 08:13
Show Gist options
  • Save airekans/cb1aa205c76de82a895d to your computer and use it in GitHub Desktop.
Save airekans/cb1aa205c76de82a895d to your computer and use it in GitHub Desktop.
Closure implementation with c++11 variadic template.
// Test in gcc 4.8.1.
#include <tuple>
#include <iostream>
template<typename T> struct ParamTrait { typedef T& ForwardType; typedef T StoreType; };
template<> struct ParamTrait<int> { typedef int ForwardType; typedef int StoreType; };
class Closure
{
public:
virtual ~Closure() {}
virtual void Run() = 0;
};
template<typename ReturnType, typename... Args>
class FunctionClosure : public Closure
{
typedef ReturnType (*Function)(Args...);
typedef ::std::tuple<typename ParamTrait<Args>::StoreType...> ArgTuple;
public:
explicit FunctionClosure(Function func, typename ParamTrait<Args>::ForwardType... args)
: m_func(func), m_args(args...) // a copy overhead here
{}
virtual void Run()
{
typedef typename ::std::_Build_index_tuple<sizeof...(Args)>::__type _Indexes;
this->call(_Indexes());
delete this;
}
private:
template<std::size_t... _Indexes>
void call(::std::_Index_tuple<_Indexes...>)
{
(void) (*m_func)(::std::get<_Indexes>(m_args)...);
}
Function m_func;
ArgTuple m_args;
};
template<typename ReturnType, typename... Args>
Closure* NewCallback(ReturnType (*func)(Args...), typename ParamTrait<Args>::ForwardType... args)
{
return new FunctionClosure<ReturnType, Args...>(func, args...);
}
static void test_func() { ::std::cout << "test_func" << ::std::endl; }
static int test_func1(int i) { ::std::cout << "test_func1" << ::std::endl; return i; }
struct TestObj {};
static int test_func2(int i, TestObj) { ::std::cout << "test_func2" << ::std::endl; return i; }
int main()
{
Closure* done = NewCallback(&test_func);
done->Run();
done = NewCallback(&test_func1, 1);
done->Run();
TestObj obj;
done = NewCallback(&test_func2, 1, obj);
done->Run();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment