Yes it is possible:
// we need a compile-time helper to generate indices template< std::size_t... Ns > struct indices { typedef indices< Ns..., sizeof...( Ns ) > next; }; template< std::size_t N > struct make_indices { typedef typename make_indices< N - 1 >::type::next type; }; template<> struct make_indices< 0 > { typedef indices<> type; };
With these helpers, you need one forwarder for your function:
template<typename R, typename... Args, std::size_t... Ns> R myFunctionImpl(void *Data, void *function, indices<Ns...> ) { auto f = (R (*)(Args...))function; return f(read<Args>(Data, Ns + 1)...);
EDIT: How does it work? First, we determine the size of the package of Args arguments through sizeof... make_indices<N>::type then expanded to indices<0,1,2,...,N-1> . It is set as an additional parameter for the implementation function (from the forwarder, which only creates a dummy instance), therefore, the deduction argument is launched on the side of the implementation function and places the generated indexes in the package of arguments Ns .
The implementation function now has two packages of arguments with the same size, namely Args and Ns . When expanding with an ellipse ... , the ellipsis expands the entire expression to which it applies, and simultaneously expands all the parameter packets! In the above example, this is the read<Args>(Data, Ns+1) expression, which extends perfectly into the OP pseudo-code.
Daniel Frey
source share