はい、可能です:
// 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;
};
これらのヘルパーでは、次のように関数に 1 つのフォワーダーが必要です。
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)...);// +1 because indices is zero-based
}
template<typename R, typename... Args>
R myFunction(void *Data, void *function) {
return myFunctionImpl< R, Args... >( Data, function, typename make_indices<sizeof...(Args)>::type() );
}
編集:どのように機能しますか?まず、引数 pack Args
のサイズを で決定しますsizeof...
。make_indices<N>::type
に展開されindices<0,1,2,...,N-1>
ます。これは実装関数への追加パラメーターとして (ダミー インスタンスを作成するフォワーダーから) 与えられるため、実装関数側で引数推定が開始され、生成されたインデックスが引数 pack に入れられますNs
。
実装関数には、同じサイズの 2 つの引数パック、つまりArgs
とが含まれるようになりNs
ました。省略記号を使用して展開する...
と、省略記号は適用される式全体を展開し、すべてのパラメーター パックを並行して展開します。上記の例では、式はread<Args>(Data, Ns+1)
であり、OP の擬似コードにうまく展開されます。