#include <functional>
#include <iostream>
#include <string>
#include <cassert>
// Call f with one argument
template <class Fn, class Arg>
auto call(const Fn &f, const Arg & arg) -> decltype(f(arg)) {
return f(arg);
}
// Helper functor for the function below
template<class Fn1, class Fn2>
class CompFn {
Fn1 a;
Fn2 b;
public:
CompFn(const Fn1 &f1, const Fn2 &f2) : a(f1), b(f2) {}
template<class Arg> inline
auto operator()(const Arg & arg) const -> decltype(call(b, call(a, arg))) {
return call(b, call(a, arg));
}
};
/** Composition of f1 and f2 (f2 after f1). */
template<class Fn1, class Fn2>
CompFn<Fn1,Fn2> comp(const Fn1 &f1, const Fn2 &f2) {
return CompFn<Fn1,Fn2>(f1, f2);
}
int main() {
// Example: Take the length of the string and compare it against zero.
std::function<int(std::string)> stringLength = [](std::string s) { return s.size(); };
std::function<bool(int)> greaterZero = [](int x) { return x > 0; };
std::function<bool(std::string)> stringNotEmpty = comp(stringLength, greaterZero);
std::string testInput1 = "foo";
std::string testInput2 = "";
assert(call(stringNotEmpty,testInput1) == true);
assert(call(stringNotEmpty,testInput2) == false);
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPGNhc3NlcnQ+CgovLyBDYWxsIGYgd2l0aCBvbmUgYXJndW1lbnQKdGVtcGxhdGUgPGNsYXNzIEZuLCBjbGFzcyBBcmc+CmF1dG8gY2FsbChjb25zdCBGbiAmZiwgY29uc3QgQXJnICYgYXJnKSAtPiBkZWNsdHlwZShmKGFyZykpIHsKICAgIHJldHVybiBmKGFyZyk7Cn0KCi8vIEhlbHBlciBmdW5jdG9yIGZvciB0aGUgZnVuY3Rpb24gYmVsb3cKdGVtcGxhdGU8Y2xhc3MgRm4xLCBjbGFzcyBGbjI+CmNsYXNzIENvbXBGbiB7CiAgICBGbjEgYTsKICAgIEZuMiBiOwoKcHVibGljOgogICAgQ29tcEZuKGNvbnN0IEZuMSAmZjEsIGNvbnN0IEZuMiAmZjIpIDogYShmMSksIGIoZjIpIHt9CgogICAgdGVtcGxhdGU8Y2xhc3MgQXJnPiBpbmxpbmUKICAgIGF1dG8gb3BlcmF0b3IoKShjb25zdCBBcmcgJiBhcmcpIGNvbnN0IC0+IGRlY2x0eXBlKGNhbGwoYiwgY2FsbChhLCBhcmcpKSkgewogICAgICAgIHJldHVybiBjYWxsKGIsIGNhbGwoYSwgYXJnKSk7CiAgICB9Cn07CgovKiogQ29tcG9zaXRpb24gb2YgZjEgYW5kIGYyIChmMiBhZnRlciBmMSkuICovCnRlbXBsYXRlPGNsYXNzIEZuMSwgY2xhc3MgRm4yPgpDb21wRm48Rm4xLEZuMj4gY29tcChjb25zdCBGbjEgJmYxLCBjb25zdCBGbjIgJmYyKSB7CiAgICByZXR1cm4gQ29tcEZuPEZuMSxGbjI+KGYxLCBmMik7Cn0KCgoKaW50IG1haW4oKSB7CiAgICAvLyBFeGFtcGxlOiBUYWtlIHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZyBhbmQgY29tcGFyZSBpdCBhZ2FpbnN0IHplcm8uCiAgICBzdGQ6OmZ1bmN0aW9uPGludChzdGQ6OnN0cmluZyk+IHN0cmluZ0xlbmd0aCA9IFtdKHN0ZDo6c3RyaW5nIHMpIHsgcmV0dXJuIHMuc2l6ZSgpOyB9OwogICAgc3RkOjpmdW5jdGlvbjxib29sKGludCk+IGdyZWF0ZXJaZXJvID0gW10oaW50IHgpIHsgcmV0dXJuIHggPiAwOyB9OwogICAgc3RkOjpmdW5jdGlvbjxib29sKHN0ZDo6c3RyaW5nKT4gc3RyaW5nTm90RW1wdHkgPSBjb21wKHN0cmluZ0xlbmd0aCwgZ3JlYXRlclplcm8pOwogICAgCiAgICBzdGQ6OnN0cmluZyB0ZXN0SW5wdXQxID0gImZvbyI7CiAgICBzdGQ6OnN0cmluZyB0ZXN0SW5wdXQyID0gIiI7CiAgICAKICAgIGFzc2VydChjYWxsKHN0cmluZ05vdEVtcHR5LHRlc3RJbnB1dDEpID09IHRydWUpOwogICAgYXNzZXJ0KGNhbGwoc3RyaW5nTm90RW1wdHksdGVzdElucHV0MikgPT0gZmFsc2UpOwp9