#include <functional>
#include <iostream>
template<class>
class ProxyFunction;
template<class R>
class ProxyFunction<R()>
{
std::function<R()> f;
public:
ProxyFunction(std::function<R()> f) : f(f) {}
~ProxyFunction() {
f();
}
operator R() {
return f();
}
};
template<class R, class FirstArg, class ...MoreArgs>
class ProxyFunction<R(FirstArg, MoreArgs...)>
{
std::function<R(FirstArg, MoreArgs...)> f;
public:
ProxyFunction(std::function<R(FirstArg, MoreArgs...)> f) : f(f) {}
~ProxyFunction() {}
ProxyFunction<R(MoreArgs...)> operator <<(const FirstArg &a) {
return ProxyFunction<R(MoreArgs...)>([a,this](MoreArgs... moreArgs) {
return f(a, moreArgs...);
});
}
};
template<class R, class ...Args>
auto makeProxy(const std::function<R(Args...)> & f) -> ProxyFunction<R(Args...)> {
return ProxyFunction<R(Args...)>(f);
}
template<class R, class ...Args>
auto makeProxy(R (*f)(Args...)) -> ProxyFunction<R(Args...)> {
return ProxyFunction<R(Args...)>(std::function<R(Args...)>(f));
}
int add(int a, int b) {
return a + b;
}
int main() {
int a = 42;
int b = 10;
auto f = makeProxy(&add);
std::cout << (f << a << b) << std::endl;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPGNsYXNzPgpjbGFzcyBQcm94eUZ1bmN0aW9uOwoKCnRlbXBsYXRlPGNsYXNzIFI+CmNsYXNzIFByb3h5RnVuY3Rpb248UigpPgp7CiAgICBzdGQ6OmZ1bmN0aW9uPFIoKT4gZjsKCnB1YmxpYzoKICAgIFByb3h5RnVuY3Rpb24oc3RkOjpmdW5jdGlvbjxSKCk+IGYpIDogZihmKSB7fQogICAgflByb3h5RnVuY3Rpb24oKSB7CiAgICAgICAgZigpOwogICAgfQogICAgb3BlcmF0b3IgUigpIHsKICAgICAgICByZXR1cm4gZigpOwogICAgfQp9OwoKCnRlbXBsYXRlPGNsYXNzIFIsIGNsYXNzIEZpcnN0QXJnLCBjbGFzcyAuLi5Nb3JlQXJncz4KY2xhc3MgUHJveHlGdW5jdGlvbjxSKEZpcnN0QXJnLCBNb3JlQXJncy4uLik+CnsKICAgIHN0ZDo6ZnVuY3Rpb248UihGaXJzdEFyZywgTW9yZUFyZ3MuLi4pPiBmOwoKcHVibGljOgogICAgUHJveHlGdW5jdGlvbihzdGQ6OmZ1bmN0aW9uPFIoRmlyc3RBcmcsIE1vcmVBcmdzLi4uKT4gZikgOiBmKGYpIHt9CiAgICB+UHJveHlGdW5jdGlvbigpIHt9CgogICAgUHJveHlGdW5jdGlvbjxSKE1vcmVBcmdzLi4uKT4gb3BlcmF0b3IgPDwoY29uc3QgRmlyc3RBcmcgJmEpIHsKICAgICAgICByZXR1cm4gUHJveHlGdW5jdGlvbjxSKE1vcmVBcmdzLi4uKT4oW2EsdGhpc10oTW9yZUFyZ3MuLi4gbW9yZUFyZ3MpIHsKICAgICAgICAgICAgcmV0dXJuIGYoYSwgbW9yZUFyZ3MuLi4pOwogICAgICAgIH0pOwogICAgfQp9OwoKCgoKdGVtcGxhdGU8Y2xhc3MgUiwgY2xhc3MgLi4uQXJncz4KYXV0byBtYWtlUHJveHkoY29uc3Qgc3RkOjpmdW5jdGlvbjxSKEFyZ3MuLi4pPiAmIGYpIC0+IFByb3h5RnVuY3Rpb248UihBcmdzLi4uKT4gewogICAgcmV0dXJuIFByb3h5RnVuY3Rpb248UihBcmdzLi4uKT4oZik7Cn0KdGVtcGxhdGU8Y2xhc3MgUiwgY2xhc3MgLi4uQXJncz4KYXV0byBtYWtlUHJveHkoUiAoKmYpKEFyZ3MuLi4pKSAtPiBQcm94eUZ1bmN0aW9uPFIoQXJncy4uLik+IHsKICAgIHJldHVybiBQcm94eUZ1bmN0aW9uPFIoQXJncy4uLik+KHN0ZDo6ZnVuY3Rpb248UihBcmdzLi4uKT4oZikpOwp9CgoKCmludCBhZGQoaW50IGEsIGludCBiKSB7CiAgICByZXR1cm4gYSArIGI7Cn0KCgoKaW50IG1haW4oKSB7CiAgICBpbnQgYSA9IDQyOwogICAgaW50IGIgPSAxMDsKICAgIGF1dG8gZiA9IG1ha2VQcm94eSgmYWRkKTsKICAgIHN0ZDo6Y291dCA8PCAoZiA8PCBhIDw8IGIpIDw8IHN0ZDo6ZW5kbDsKfQo=