#include <functional>
namespace _dtl {
template <typename FUNCTION> struct
_curry;
// specialization for functions with a single argument
template <typename R,typename T> struct
_curry<std::function<R(T)>> {
using
type = std::function<R(T)>;
const type
result;
_curry(type fun) : result(fun) {}
};
// recursive specialization for functions with more arguments
template <typename R,typename T,typename...Ts> struct
_curry<std::function<R(T,Ts...)>> {
using
remaining_type = typename _curry<std::function<R(Ts...)> >::type;
using
type = std::function<remaining_type(T)>;
const type
result;
_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;
}
) {}
};
}
template <typename R,typename...Ts> auto
curry(const std::function<R(Ts...)> fun)
-> typename _dtl::_curry<std::function<R(Ts...)>>::type
{
return _dtl::_curry<std::function<R(Ts...)>>(fun).result;
}
template <typename R,typename...Ts> auto
curry(R(* const fun)(Ts...))
-> typename _dtl::_curry<std::function<R(Ts...)>>::type
{
return _dtl::_curry<std::function<R(Ts...)>>(fun).result;
}
#include <iostream>
void
f(std::string a,std::string b,std::string c)
{
std::cout << a << b << c;
}
int
main() {
curry(f)("Hello ")("functional ")("world!");
return 0;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CgpuYW1lc3BhY2UgX2R0bCB7CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEZVTkNUSU9OPiBzdHJ1Y3QKICAgIF9jdXJyeTsKCiAgICAvLyBzcGVjaWFsaXphdGlvbiBmb3IgZnVuY3Rpb25zIHdpdGggYSBzaW5nbGUgYXJndW1lbnQKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBSLHR5cGVuYW1lIFQ+IHN0cnVjdAogICAgX2N1cnJ5PHN0ZDo6ZnVuY3Rpb248UihUKT4+IHsKICAgICAgICB1c2luZwogICAgICAgIHR5cGUgPSBzdGQ6OmZ1bmN0aW9uPFIoVCk+OwoKICAgICAgICBjb25zdCB0eXBlCiAgICAgICAgcmVzdWx0OwoKICAgICAgICBfY3VycnkodHlwZSBmdW4pIDogcmVzdWx0KGZ1bikge30KCiAgICB9OwoKICAgIC8vIHJlY3Vyc2l2ZSBzcGVjaWFsaXphdGlvbiBmb3IgZnVuY3Rpb25zIHdpdGggbW9yZSBhcmd1bWVudHMKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBSLHR5cGVuYW1lIFQsdHlwZW5hbWUuLi5Ucz4gc3RydWN0CiAgICBfY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFQsVHMuLi4pPj4gewogICAgICAgIHVzaW5nCiAgICAgICAgcmVtYWluaW5nX3R5cGUgPSB0eXBlbmFtZSBfY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4gPjo6dHlwZTsKCiAgICAgICAgdXNpbmcKICAgICAgICB0eXBlID0gc3RkOjpmdW5jdGlvbjxyZW1haW5pbmdfdHlwZShUKT47CgogICAgICAgIGNvbnN0IHR5cGUKICAgICAgICByZXN1bHQ7CgogICAgICAgIF9jdXJyeShzdGQ6OmZ1bmN0aW9uPFIoVCxUcy4uLik+IGZ1bikKICAgICAgICA6IHJlc3VsdCAoCiAgICAgICAgICAgIFs9XShjb25zdCBUJiB0KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gX2N1cnJ5PHN0ZDo6ZnVuY3Rpb248UihUcy4uLik+PigKICAgICAgICAgICAgICAgICAgICBbPV0oY29uc3QgVHMmLi4udHMpeyAKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bih0LCB0cy4uLik7IAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICkucmVzdWx0OwogICAgICAgICAgICB9CiAgICAgICAgKSB7fQogICAgfTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFIsdHlwZW5hbWUuLi5Ucz4gYXV0bwpjdXJyeShjb25zdCBzdGQ6OmZ1bmN0aW9uPFIoVHMuLi4pPiBmdW4pCi0+IHR5cGVuYW1lIF9kdGw6Ol9jdXJyeTxzdGQ6OmZ1bmN0aW9uPFIoVHMuLi4pPj46OnR5cGUKewogICAgcmV0dXJuIF9kdGw6Ol9jdXJyeTxzdGQ6OmZ1bmN0aW9uPFIoVHMuLi4pPj4oZnVuKS5yZXN1bHQ7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBSLHR5cGVuYW1lLi4uVHM+IGF1dG8KY3VycnkoUigqIGNvbnN0IGZ1bikoVHMuLi4pKQotPiB0eXBlbmFtZSBfZHRsOjpfY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4+Ojp0eXBlCnsKICAgIHJldHVybiBfZHRsOjpfY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4+KGZ1bikucmVzdWx0Owp9CgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp2b2lkIApmKHN0ZDo6c3RyaW5nIGEsc3RkOjpzdHJpbmcgYixzdGQ6OnN0cmluZyBjKQp7CiAgICBzdGQ6OmNvdXQgPDwgYSA8PCBiIDw8IGM7Cn0KCmludCAKbWFpbigpIHsKICAgIGN1cnJ5KGYpKCJIZWxsbyAiKSgiZnVuY3Rpb25hbCAiKSgid29ybGQhIik7CiAgICByZXR1cm4gMDsKfQ==