Skip to content

Instantly share code, notes, and snippets.

@drvink
Created September 19, 2015 03:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drvink/72ae3dd6bdf09ef19af0 to your computer and use it in GitHub Desktop.
Save drvink/72ae3dd6bdf09ef19af0 to your computer and use it in GitHub Desktop.
currying in C++11
#include <functional>
#include <type_traits>
#include <utility>
#include <cstdlib>
/*
* from:
* http://nvwa.cvs.sourceforge.net/viewvc/nvwa/nvwa/functional.h?view=markup
*
* rewritten for C++11
*/
namespace curry {
namespace detail {
template <
typename a,
bool _deep_copy = (std::is_rvalue_reference<a>{} ||
(std::is_lvalue_reference<a>{} &&
std::is_const<std::remove_reference<a> >{}))
>
struct data {
data(a&& x)
: value(std::forward<a>(x))
{}
auto get() const -> a { return value; }
a value;
};
template <typename a>
struct data<a, true> {
data(a&& x)
: value(std::forward<a>(x))
{}
template <typename b = a>
auto get() const ->
std::enable_if<std::is_rvalue_reference<b>{}, std::decay<a> >
{
return value;
}
template <typename b = a>
auto get() const ->
std::enable_if<!std::is_rvalue_reference<b>{}, a>
{
return value;
}
std::decay<a> value;
};
template <typename f>
struct curry;
template <typename r, typename t>
struct curry<std::function<r (t)> > {
using type = std::function<r (t)>;
static auto mk(const type& fn) -> type { return fn; }
};
template <typename r, typename t, typename... ts>
struct curry<std::function<r (t, ts...)> > {
using tt = typename curry<std::function<r (ts...)> >::type;
using type = std::function<tt (t)>;
static auto mk(const std::function<r (t, ts...)>& fn) -> type
{
return [fn](t&& x)
{
auto x_ = data<t>(std::forward<t>(x));
return curry<std::function<r (ts...)> >::mk(
[fn, x_](
ts&&... args) ->
decltype(fn(x_.get(),
std::forward<ts>(args)...))
{
return fn(x_.get(), std::forward<ts>(args)...);
});
};
}
};
};
template <typename r, typename... ts>
auto
curry(std::function<r (ts...)> fn) ->
typename detail::curry<std::function<r (ts...)> >::type
{
return detail::curry<std::function<r (ts...)> >::mk(fn);
}
template <typename r, typename... ts>
auto
curry(r (*fn)(ts...)) -> typename detail::curry<std::function<r (ts...)> >::type
{
return detail::curry<std::function<r (ts...)> >::mk(fn);
}
};
auto
tupled(const char* a, const char* b, const char* c) -> void
{
printf("%s%s%s", a, b, c);
}
auto
main() -> int
{
auto f = curry::curry(tupled)("yo ")("homie\n");
f("how is it going dude.\n");
return EXIT_SUCCESS;
}
#include <functional>
#include <cstdlib>
namespace curry { namespace detail {
template <typename f>
struct curry;
template <typename r, typename t>
struct curry<std::function<r (t)> > {
using type = std::function<r (t)>;
curry(type fun)
: result(fun)
{}
const type result;
};
template <typename r, typename t, typename... ts>
struct curry<std::function<r (t, ts...)> > {
using tt = typename curry<std::function<r (ts...)> >::type;
using type = std::function<tt (t)>;
curry(std::function<r (t, ts...)> fun)
: result(
[=](const t& t_)
{
return curry<std::function<r (ts...)> >(
[=](const ts& ...ts_) { return fun(t_, ts_...); }
).result;
})
{}
const type result;
};
};
template <typename r, typename... ts>
auto
curry(const std::function<r (ts...)> fun) ->
typename detail::curry<std::function<r (ts...)> >::type
{
return detail::curry<std::function<r (ts...)> >(fun).result;
}
template <typename r, typename... ts>
auto
curry(r (* const fun)(ts...)) ->
typename detail::curry<std::function<r (ts...)> >::type
{
return detail::curry<std::function<r (ts...)> >(fun).result;
}
};
auto
tupled(const char* a, const char* b, const char* c) -> void
{
printf("%s%s%s", a, b, c);
}
auto
main() -> int
{
auto f = curry::curry(tupled)("yo ")("homie\n");
f("how is it going dude.\n");
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment