#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+CgpuYW1lc3BhY2UgX19kdGwgewoKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBGVU5DVElPTj4gc3RydWN0CiAgICBfX2N1cnJ5OwoKICAgIC8vIHNwZWNpYWxpemF0aW9uIGZvciBmdW5jdGlvbnMgd2l0aCBhIHNpbmdsZSBhcmd1bWVudAogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFIsdHlwZW5hbWUgVD4gc3RydWN0CiAgICBfX2N1cnJ5PHN0ZDo6ZnVuY3Rpb248UihUKT4+IHsKICAgICAgICB1c2luZwogICAgICAgIHR5cGUgPSBzdGQ6OmZ1bmN0aW9uPFIoVCk+OwoKICAgICAgICBjb25zdCB0eXBlCiAgICAgICAgcmVzdWx0OwoKICAgICAgICBfX2N1cnJ5KHR5cGUgZnVuKSA6IHJlc3VsdChmdW4pIHt9CgogICAgfTsKCiAgICAvLyByZWN1cnNpdmUgc3BlY2lhbGl6YXRpb24gZm9yIGZ1bmN0aW9ucyB3aXRoIG1vcmUgYXJndW1lbnRzCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgUix0eXBlbmFtZSBULHR5cGVuYW1lLi4uVHM+IHN0cnVjdAogICAgX19jdXJyeTxzdGQ6OmZ1bmN0aW9uPFIoVCxUcy4uLik+PiB7CiAgICAgICAgdXNpbmcKICAgICAgICByZW1haW5pbmdfdHlwZSA9IHR5cGVuYW1lIF9fY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4gPjo6dHlwZTsKCiAgICAgICAgdXNpbmcKICAgICAgICB0eXBlID0gc3RkOjpmdW5jdGlvbjxyZW1haW5pbmdfdHlwZShUKT47CgogICAgICAgIGNvbnN0IHR5cGUKICAgICAgICByZXN1bHQ7CgogICAgICAgIF9fY3Vycnkoc3RkOjpmdW5jdGlvbjxSKFQsVHMuLi4pPiBmdW4pCiAgICAgICAgOiByZXN1bHQgKAogICAgICAgICAgICBbPV0oY29uc3QgVCYgdCkgewogICAgICAgICAgICAgICAgcmV0dXJuIF9fY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4+KAogICAgICAgICAgICAgICAgICAgIFs9XShjb25zdCBUcyYuLi50cyl7IAogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuKHQsIHRzLi4uKTsgCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgKS5yZXN1bHQ7CiAgICAgICAgICAgIH0KICAgICAgICApIHt9CiAgICB9Owp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUix0eXBlbmFtZS4uLlRzPiBhdXRvCmN1cnJ5KGNvbnN0IHN0ZDo6ZnVuY3Rpb248UihUcy4uLik+IGZ1bikKLT4gdHlwZW5hbWUgX19kdGw6Ol9fY3Vycnk8c3RkOjpmdW5jdGlvbjxSKFRzLi4uKT4+Ojp0eXBlCnsKICAgIHJldHVybiBfX2R0bDo6X19jdXJyeTxzdGQ6OmZ1bmN0aW9uPFIoVHMuLi4pPj4oZnVuKS5yZXN1bHQ7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBSLHR5cGVuYW1lLi4uVHM+IGF1dG8KY3VycnkoUigqIGNvbnN0IGZ1bikoVHMuLi4pKQotPiB0eXBlbmFtZSBfX2R0bDo6X19jdXJyeTxzdGQ6OmZ1bmN0aW9uPFIoVHMuLi4pPj46OnR5cGUKewogICAgcmV0dXJuIF9fZHRsOjpfX2N1cnJ5PHN0ZDo6ZnVuY3Rpb248UihUcy4uLik+PihmdW4pLnJlc3VsdDsKfQoKI2luY2x1ZGUgPGlvc3RyZWFtPgoKdm9pZCAKZihzdGQ6OnN0cmluZyBhLHN0ZDo6c3RyaW5nIGIsc3RkOjpzdHJpbmcgYykKewogICAgc3RkOjpjb3V0IDw8IGEgPDwgYiA8PCBjOwp9CgppbnQgCm1haW4oKSB7CiAgICBjdXJyeShmKSgiSGVsbG8gIikoImZ1bmN0aW9uYWwgIikoIndvcmxkISIpOwogICAgcmV0dXJuIDA7Cn0=