#include #include #include #include template struct _apply { template static _Ret run(std::function<_Ret(_Fargs...)> fn, std::tuple<_Targs...> t, _Oargs... o) { return _apply::run(fn, t, std::get(t), o...); } }; template<> struct _apply<0> { template static _Ret run(std::function<_Ret(_Fargs...)> fn, std::tuple<_Targs...> t, _Oargs... o) { return fn(o...); } }; template _Ret apply(std::function<_Ret(_Fargs...)> fn, std::tuple<_Targs...> t, _Oargs... o) { return _apply::run(fn, t, o...); } template struct __if { typedef A result; }; template struct __if<0, A, B> { typedef B result; }; template struct _reverse_tuple; template struct _reverse_tuple, std::tuple<_Dest...>> { typedef std::tuple<_Dest...> result; }; template struct _reverse_tuple, std::tuple<_Dest...>> { typedef typename _reverse_tuple, std::tuple<_Orig1, _Dest...>>::result result; }; template struct reverse_tuple { typedef typename _reverse_tuple, std::tuple<>>::result result; }; template struct reverse_tuple> { typedef typename _reverse_tuple, std::tuple<>>::result result; }; template struct prepend_tuple; template struct prepend_tuple, _Y> { typedef std::tuple<_Y, _X...> result; }; template struct append_tuple; template struct append_tuple, _Y> { private: typedef typename reverse_tuple<_X...>::result reversed; typedef typename prepend_tuple::result prepended; public: typedef typename reverse_tuple::result result; }; template struct tuple_maker; template struct tuple_maker> { static std::tuple<_X...> create(_X... x) { return std::tuple<_X...>(x...); } typedef std::function(_X...)> function_type; }; template class curryable_impl_base; template class curryable_impl_base<_Ret(_Arg)> { protected: typedef _Arg _NextArg; public: virtual _Ret operator()(_Arg) = 0; }; template class curryable_impl_base<_Ret(_Arg, _Args...)> { protected: typedef _Arg _NextArg; public: typedef curryable_impl_base<_Ret(_Args...)> _Next_base; virtual std::shared_ptr<_Next_base> operator()(_Arg) = 0; }; template struct _pop_first_n_args; template struct _pop_first_n_args<0, _Ret(_Args...), true> { typedef _Ret result(_Args...); }; template struct _pop_first_n_args<_N, _Ret(_Arg, _Args...), false> { typedef typename _pop_first_n_args<_N-1, _Ret(_Args...), (_N-1)==0>::result result; }; template struct pop_first_n_args { typedef typename _pop_first_n_args<_N, _Sig, _N==0>::result result; }; template class _base_for { public: typedef typename pop_first_n_args::result curried_type; typedef curryable_impl_base result; }; template class _curryable; template class _curryable<1, _Ret(_Arg, _Args...), std::tuple<_Curried...>> : public _base_for<_Ret(_Arg, _Args...), _Curried...>::result { typedef typename _base_for<_Ret(_Arg, _Args...), _Curried...>::result _BaseType; typedef std::function<_Ret(_Arg, _Args...)> function_type; function_type _fn; std::tuple<_Curried...> _items; public: _curryable(function_type f, std::tuple<_Curried...> i) : _fn(f), _items(i) { } _Ret operator()(typename _BaseType::_NextArg arg) { return apply(_fn, _items, arg); } }; template class _curryable<_N, _Ret(_Arg, _Args...), std::tuple<_Curried...>> : public _base_for<_Ret(_Arg, _Args...), _Curried...>::result { typedef typename _base_for<_Ret(_Arg, _Args...), _Curried...>::result _BaseType; typedef typename append_tuple, typename _BaseType::_NextArg>::result next_tuple_type; typedef std::function<_Ret(_Arg, _Args...)> function_type; typedef _curryable<_N-1, _Ret(_Arg, _Args...), next_tuple_type> _Next; function_type _fn; std::tuple<_Curried...> _items; public: _curryable(function_type f, std::tuple<_Curried...> c) : _fn(f), _items(c) { } std::shared_ptr operator()(typename _BaseType::_NextArg arg) { typedef tuple_maker maker; auto new_items(apply(typename maker::function_type(maker::create), _items, arg)); return std::shared_ptr<_Next>(new _Next(_fn, new_items)); } }; template class curryable; template class curryable<_Ret(_Args...)> { typedef std::shared_ptr> impl_type; impl_type _impl; public: curryable(impl_type i) : _impl(i) { } curryable(std::function<_Ret(_Args...)> fn) : _impl(new _curryable>(fn, std::tuple<>())) { } typedef typename pop_first_n_args<1, _Ret(_Args...)>::result next_sig; typedef typename __if, _Ret>::result next; template next operator()(_Arg arg) { return next(_impl->operator()(arg)); } template typename __if::result>, _Ret>::result operator()(_Arg1 arg1, _Argn... argn) { return operator()(arg1)(argn...); } }; using std::tuple; double apply_test(char const *a, int b, double c) { std::cout<<"apply_test(\""< fn1(apply_test); curryable cc(fn1); std::cout<<"Calls: "< partial(cc("foo",2)); std::cout< fn2(apply_test); std::cout<