Dynamically call lambda based on stream input: Try 3
I was about to add more things to my answer on your previous post and noticed meanwhile that your already asked a following question (that's almost too fast! :o). I have done some additional reading about C++14 and integer sequences. And I have found some things in the standard that could help to improve your code again.

I realized at some point that you were using int as the value_type of std::integer_sequence. However, you initialize your static constexpr int size with the result of sizeof... and sizeof... returns a std::size_t, not an int.

Then I remembered that, along with std::integer_sequence, there is a typedef for std::integer_sequence&lt;std::size_t, N&gt; which is called std::index_sequence and which has been made to solve the kind of problem that your are trying to solve. Therefore, you should every occurrence of int by std::size_t and of std::integer_sequence&lt;int, N&gt; by std::index_sequence&lt;N&gt;.



Moreover, you don't need to create a typedef for Sequence in CallerTraits: you can deduce this class directly in callFunctor thanks to CallerTraits&lt;&gt;::size:

template&lt;typename StreamValueGetter, typename Action, typename Stream&gt;
void callFunctor(Stream&amp; stream, Action action)
{
    using Sequence = std::make_index_sequence&lt;CallerTraits&lt;Action&gt;::size&gt;;
    expandArgsAndCallFunctor&lt;StreamValueGetter&gt;(stream, action, Sequence());
}


Note that I also replaced decltype(action) by Action since it is the same type.



Also, you can get rid of the public inheritance specifier for CallerTraits since you are using a struct. That does not change anything whatsoever.



Here is your code once refactored. I don't provide a link to an online compiler since none of the ones available has a good enough C++14 support (you just need to add some light library components though):

template &lt;typename T&gt;
struct CallerTraits
    : CallerTraits&lt;decltype(&amp;T::operator())&gt;
{};

template&lt;typename C, typename ...Args&gt;
struct CallerTraits&lt;void (C::*)(Args...) const&gt;
{
    static constexpr std::size_t                size = sizeof...(Args);
    typedef std::tuple&lt;std::decay_t&lt;Args&gt;...&gt;   AllArgs;
};

template&lt;typename StreamValueGetter, typename Action, typename Stream, std::size_t... S&gt;
void expandArgsAndCallFunctor(Stream&amp; stream, Action action, std::index_sequence&lt;S...&gt;)
{
    typedef CallerTraits&lt;Action&gt;        Trait;
    typedef typename Trait::AllArgs     ArgumentTuple;

    // ArgumentTuple  arguments(StreamValueGetter::template get&lt;typename std::tuple_element&lt;S, ArgumentTuple&gt;::type&gt;(stream)...);
    // action(std::get&lt;S&gt;(arguments)...);

    // The above two commented out lines
    // Represent the logic of the following line which retrieves
    // and calls the arguments in a single line thus avoiding temporaries.
    action(StreamValueGetter::template get&lt;std::tuple_element_t&lt;S, ArgumentTuple&gt;&gt;(stream)...);
}

template&lt;typename StreamValueGetter, typename Action, typename Stream&gt;
void callFunctor(Stream&amp; stream, Action action)
{
    using Sequence = std::make_index_sequence&lt;CallerTraits&lt;Action&gt;::size&gt;;
    expandArgsAndCallFunctor&lt;StreamValueGetter&gt;(stream, action, Sequence());
}