C++ function composition What is a good way to compose std::function objects in C++?

I tried the following, and it seems to work well:

template&lt;typename ... Fs&gt;
struct compose_impl
{
    compose_impl(Fs&amp;&amp; ... fs) : functionTuple(std::forward_as_tuple(fs ...)) {}

    template&lt;std::size_t&gt; struct int2type{};

    template&lt;size_t N, typename ... Ts&gt;
    auto apply(int2type&lt;N&gt;, Ts&amp;&amp; ... ts)
    {
        return std::get&lt;N&gt;(functionTuple)(apply(int2type&lt;N+1&gt;(),std::forward&lt;Ts&gt;(ts)...));
    }

    static const size_t size = sizeof ... (Fs);
    template&lt;typename ... Ts&gt;
    auto apply(int2type&lt;size-1&gt;, Ts&amp;&amp; ... ts)
    {
        return std::get&lt;size-1&gt;(functionTuple)(std::forward&lt;Ts&gt;(ts)...);
    }

    template&lt;typename ... Ts&gt;
    auto operator()(Ts&amp;&amp; ... ts)
    {
        return apply(int2type&lt;0&gt;(), std::forward&lt;Ts&gt;(ts)...);
    }

    std::tuple&lt;Fs ...&gt; functionTuple;
};

template&lt;typename ... Fs&gt;
auto compose(Fs&amp;&amp; ... fs)
{
    return compose_impl&lt;Fs ...&gt;(std::forward&lt;Fs&gt;(fs) ...);
}


With this, one can compose functions as long as the signatures fit together. Example:

auto f1 = [](std::pair&lt;double,double&gt; 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 &lt;&lt; g(2.0, 3.0) &lt;&lt; std::endl;   //prints '13', evaluated as (2*3) + ((2*3)+1)


Comments and suggestions for improvement are welcome!
Generally speaking, it is really well done, for several reasons: std::tuple often takes advantage of the empty base class optimization, which means that since you feed it lambdas, your class will often weigh almost nothing, and everything is correctly forwarded. The only things I see that could be improved are the following ones:


You could const-qualify apply and operator().
size should be static constexpr instead of static const to make it even clearer that it is a compile-time constant.
You should be consistent when qualifying std::size_t: either use the prefix std:: or leave it, but stay consistent.


As you can see, these are really minor improvements. I also have some other remarks, but those will be opinions more than actual advice:


int2type kind of already exists in the standard and is named std::integral_constant. However, I will concede that it takes another template parameter for the type and that it might be too verbose for your needs.
I had some trouble understanding how your recursion worked because it was in ascending order. For some reason, I am more used to descending order. I would have overloaded apply for int2type&lt;0&gt; and not for int2type&lt;size-1&gt; and performed a descending recursion. That would have allowed me to write:

template&lt;typename ... Ts&gt;
auto operator()(Ts&amp;&amp; ... ts)
{
    return apply(int2type&lt;sizeof ... (Fs) - 1&gt;(), std::forward&lt;Ts&gt;(ts)...);
}


And then, size wouldn't have had to be a member of the class anymore. But I have to admit that this is an opinion and not a guideline. Your code is good enough that I see almost nothing that could be improved :)