Skip to content

Instantly share code, notes, and snippets.

@quartorz
Created July 21, 2014 10:55
Show Gist options
  • Save quartorz/dd302779e56a552f8c88 to your computer and use it in GitHub Desktop.
Save quartorz/dd302779e56a552f8c88 to your computer and use it in GitHub Desktop.
#include <iostream>
#include "sprout/tuple/tuple.hpp"
#include "sprout/index_tuple/make_index_sequence.hpp"
#include "sprout/index_tuple/make_indexes.hpp"
template <class Func, int N, int M, class... Args>
class curry{
Func f;
sprout::tuple<Args...> args;
public:
template <class... IArgs>
constexpr curry(Func f, IArgs... args)
: f(f)
, args(args...)
{
}
template <class Arg>
constexpr auto operator()(Arg a)
{
using namespace sprout;
return operator_helper(make_indexes<make_index_tuple<N-M>>(), a);
}
private:
template <int... I, class Arg>
constexpr auto operator_helper(typename sprout::integer_sequence<int, I...>::type&&, Arg a)
{
return curry<Func, N, M-1, Args..., Arg>(std::forward(f), sprout::tuple_get<I>(args)..., a);
}
};
template <class Func, int N>
class curry<Func, N, N>{
Func f;
public:
constexpr curry(Func f) : f(f)
{
}
template <class Arg>
constexpr auto operator()(Arg a)
{
return curry<Func, N, N-1, Arg>(f, a);
}
};
template <class Func, int N, class... Args>
class curry<Func, N, 1, Args...>{
Func f;
sprout::tuple<Args...> args;
public:
template <class... IArgs>
constexpr curry(Func f, IArgs... args)
: f(f)
, args(args...)
{
}
template <class Arg>
constexpr auto operator()(Arg a)
{
using namespace sprout;
return operator_helper(make_indexes<make_index_tuple<N-1>>(), a);
}
private:
template <int... I, class Arg>
constexpr auto operator_helper(sprout::integer_sequence<int, I...>&&, Arg a)
{
return f(sprout::tuple_get<I>(args)..., a);
}
};
template <class Func>
class curry<Func, 0, 0>{
Func f;
public:
constexpr curry(Func f) : f(f)
{
}
constexpr auto operator()()
{
return f();
}
};
template <class Func, class... Args>
class curry_variadic{
Func f;
sprout::tuple<Args...> args;
public:
template <class... IArgs>
constexpr curry_variadic(Func f, IArgs... args)
: f(f)
, args(args...)
{
}
template <class Arg>
constexpr auto operator()(Arg a)
{
using namespace sprout;
return operator_helper(make_indexes<make_index_tuple<sizeof...(Args)>>(), a);
}
constexpr auto operator()()
{
using namespace sprout;
return operator_helper(make_indexes<make_index_tuple<sizeof...(Args)>>());
}
private:
template <int... I, class Arg>
constexpr auto operator_helper(sprout::integer_sequence<int, I...>&&, Arg a)
{
return curry_variadic<Func, Args..., Arg>(f, sprout::tuple_get<I>(args)..., a);
}
template <int... I>
constexpr auto operator_helper(sprout::integer_sequence<int, I...>&&)
{
return f(sprout::tuple_get<I>(args)...);
}
};
template <class Func>
class curry_variadic<Func>{
Func f;
public:
constexpr curry_variadic(Func f)
: f(f)
{
}
template <class Arg>
constexpr auto operator()(Arg a)
{
return curry_variadic<Func, Arg>(f, a);
}
constexpr auto operator()()
{
return f();
}
};
template <class... Args, class Func>
constexpr auto make_curry(Func f)
{
return curry<Func, sizeof...(Args), sizeof...(Args)>(f);
}
template <int N, class Func>
constexpr auto make_curry_n(Func f)
{
return curry<Func, N, N>(f);
}
template <class Func>
constexpr auto make_curry_variadic(Func f)
{
return curry_variadic<Func>(f);
}
constexpr int func(int a, double b)
{
return 100;
}
constexpr int func2(int a, int b, int c)
{
return a + b + c;
}
int main()
{
constexpr int a = make_curry<int, double>(func)(1)(1.5);
constexpr int b = make_curry_n<2>(func)(2)(2.5);
constexpr int c = make_curry_variadic(func2)(1)(2)(3)();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment