9

可変数のテンプレート引数を取る関数を作成したいと思います。後でこれらの引数を使用して、関数は次のように位置を渡す必要があります。

template<typename R, typename Args...>
R myFunction(Data &data, void *function) {
    auto f = (R (*)(Args...))function;
    return f(read<Args1>(data, 1), read<Args2>(data, 2), ...);// <-- This is the problem
}

もちろん、指定されたコードはコンパイルできません。それを修正する方法はありますか?コードをあまり複製せずに、可変個引数テンプレートなしでそれを行う方法はありますか?

4

1 に答える 1

17

はい、可能です:

// 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 の擬似コードにうまく展開されます。

于 2013-03-04T15:13:20.527 に答える