を展開するための基本的な構成要素std::tuple<T...>
は、実際にはコードから省略されています。2 番目のパラメーターを取得するstd::tuple<...>
必要があります0, 1, ..., n
。これら 2 つのパラメーター パックを取得したら、それらを連携して展開できます。
template <typename F, typename... T, int... N>
void call_impl(F&& fun, std::tuple<T...>&& t) {
fun(std::get<N>(t)...);
}
本当の魔法は、std::tuple<T...>
. テンプレートプログラミングが少し必要です。インデックスのリストを作成する方法は次のとおりです。
template <int... Indices> struct indices;
template <> struct indices<-1> { typedef indices<> type; };
template <int... Indices>
struct indices<0, Indices...>
{
typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...>
{
typedef typename indices<Index - 1, Index, Indices...>::type type;
};
template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices()
{
return 0;
}
call()
したがって、関数テンプレートがある場合は、関数オブジェクトと関数std::tuple<T...>
への引数を持つ を受け取る関数テンプレートを呼び出しましょう。簡単なアプローチはcall_impl()
、インデックスの推定に対処するために上記を書き直すことです。
template <typename F, typename Tuple, int... N>
void call_impl(F&& fun, Tuple&& t, indices<Indices...> const*)
{
fun(std::get<N>(t)...);
}
template <typename F, typename Tuple>
void call(F&& fun, Tuple&& t)
{
call_imle(std::forward<F>(fun), std::forward<Tuple>(t), make_indices<Tuple>());
}
このコードが実際に拡張していないのは、関数を呼び出すときstd::forward<...>()
のさまざまな要素での正しい使用です。要素を移動するのではなく、全体を移動する可能性があるため、std::tuple<...>
使用するだけでstd::forward<Tuple>(t)
は機能しません。a の適切な要素ごとの移動のようなことができるとstd::tuple<...>
思いますstd::tuple<...>
が、まだ行っていません。