-
-
Save drvink/72ae3dd6bdf09ef19af0 to your computer and use it in GitHub Desktop.
currying in C++11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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