What is a good way to compose std::function
objects in C++?
I tried the following, and it seems to work well:
template<typename ... Fs>
struct compose_impl
{
compose_impl(Fs&& ... fs) : functionTuple(std::forward_as_tuple(fs ...)) {}
template<std::size_t> struct int2type{};
template<size_t N, typename ... Ts>
auto apply(int2type<N>, Ts&& ... ts)
{
return std::get<N>(functionTuple)(apply(int2type<N+1>(),std::forward<Ts>(ts)...));
}
static const size_t size = sizeof ... (Fs);
template<typename ... Ts>
auto apply(int2type<size-1>, Ts&& ... ts)
{
return std::get<size-1>(functionTuple)(std::forward<Ts>(ts)...);
}
template<typename ... Ts>
auto operator()(Ts&& ... ts)
{
return apply(int2type<0>(), std::forward<Ts>(ts)...);
}
std::tuple<Fs ...> functionTuple;
};
template<typename ... Fs>
auto compose(Fs&& ... fs)
{
return compose_impl<Fs ...>(std::forward<Fs>(fs) ...);
}
With this, one can compose functions as long as the signatures fit together. Example:
auto f1 = [](std::pair<double,double> p) {return p.first + p.second; };
auto f2 = [](double x) {return std::make_pair(x, x + 1.0); };
auto f3 = [](double x, double y) {return x*y; };
auto g = compose(f1, f2, f3);
std::cout << g(2.0, 3.0) << std::endl; //prints '13', evaluated as (2*3) + ((2*3)+1)
Comments and suggestions for improvement are welcome!
int f(int)
andint g(int)
functors isauto h = [&](int x) { return f(g(x)); };
). What you mean by "compose" should determine if this is a good solution or not. \$\endgroup\$