Skip to content

Instantly share code, notes, and snippets.

@hisui
Last active August 29, 2015 14:04
Show Gist options
  • Save hisui/ec450c1d28e97fc4c9db to your computer and use it in GitHub Desktop.
Save hisui/ec450c1d28e97fc4c9db to your computer and use it in GitHub Desktop.
[C++14] Making a currying functor from a functor.
#include <utility>
#include <tuple>
namespace {
using std::forward;
using std::move;
using std::tuple;
template<size_t H, size_t ...T> struct apply_by_tuple
{
template<typename F, typename ...X> auto operator()(F &&f, tuple<X...> &&args)
{
return apply_by_tuple<H-1,H-1,T...>()(forward<F>(f), forward<tuple<X...>>(args));
}
};
template<size_t ...T> struct apply_by_tuple<0, T...>
{
template<typename F, typename ...X> auto operator()(F &&f, tuple<X...> &&args)
{
return forward<F>(f)(std::get<T>(args)...);
}
};
template<typename F, typename ...X> auto currying_0(F &&f, tuple<X...> &&x)
{
return call_by_tuple(forward<F>(f), forward<tuple<X...>>(x));
}
template<typename A, typename ...Args, typename F, typename ...X>
auto currying_0(F &&f, tuple<X...> &&x)
{
return [g = forward<F>(f), y = move(x)] (A &&a) {
return currying_0<Args...>(g, std::tuple_cat(y, std::make_tuple(forward<A>(a))));
};
}
template<typename F, typename T, typename R, typename ...Args>
auto currying(R(T::*func)(Args...) const, F &&f)
{
return currying_0<Args...>(forward<F>(f), tuple<>());
}
} // namespace
template<typename F> auto curried(F &&f)
{
return currying(&std::decay<F>::type::operator(), std::forward<F>(f));
}
#include "currying.hpp"
#include <stdio.h>
int main()
{
auto sum = curried([] (int a, int b, int c) { return a + b + c; });
printf("%d", sum(1)(2)(3)); // ==> 6
printf("%d", sum(2)(3)(5)); // ==> 10
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment