可能性のある複製:
タプルを可変長テンプレート関数の引数に拡張するにはどうすればよいですか?
一致する関数ポインターを呼び出すためのタプルの「アンパック」
C++ 11テンプレートでは、(テンプレートの可能性がある)関数の個々の引数としてタプルを使用する方法はありますか?
例:
私にこの機能があるとしましょう:
_void foo(int a, int b)
{
}
_
そして、私はタプルauto bar = std::make_Tuple(1, 2)
を持っています。
これを使用してfoo(1, 2)
をテンプレートで呼び出すことはできますか?
引数の数がわからないテンプレートでこれを実行したいので、単にfoo(std::get<0>(bar), std::get<1>(bar))
を意味するわけではありません。
より完全な例:
_template<typename Func, typename... Args>
void caller(Func func, Args... args)
{
auto argtuple = std::make_Tuple(args...);
do_stuff_with_Tuple(argtuple);
func(insert_magic_here(argtuple)); // <-- this is the hard part
}
_
1つの引数で機能する1つのテンプレート、2つの引数で機能する別のテンプレートなどを作成したくないことに注意してください。
次のようなものを試してください:
// implementation details, users never invoke these directly
namespace detail
{
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static void call(F f, Tuple && t)
{
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
}
};
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
{
static void call(F f, Tuple && t)
{
f(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename F, typename Tuple>
void call(F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<F, Tuple, 0 == std::Tuple_size<ttype>::value, std::Tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
}
例:
#include <cstdio>
int main()
{
auto t = std::make_Tuple("%d, %d, %d\n", 1,2,3);
call(std::printf, t);
}
いくつかの追加の魔法とstd::result_of
、おそらく、全体が正しい戻り値を返すようにすることもできます。
「インデックスタプル」(コンパイル時整数のタプル)を作成してから、インデックスをパラメーターパックとして推定する別の関数に転送し、それらをパック展開で使用して、タプルでstd::get
を呼び出します。
#include <redi/index_Tuple.h>
template<typename Func, typename Tuple, unsigned... I>
void caller_impl(Func func, Tuple&& t, redi::index_Tuple<I...>)
{
func(std::get<I>(t)...);
}
template<typename Func, typename... Args>
void caller(Func func, Args... args)
{
auto argtuple = std::make_Tuple(args...);
do_stuff_with_Tuple(argtuple);
typedef redi::to_index_Tuple<Args...> indices;
caller_impl(func, argtuple, indices());
}
index_Tuple
の実装は https://gitlab.com/redistd/redistd/blob/master/include/redi/index_Tuple.h にありますが、コンパイラーがテンプレートエイリアスに依存しているため、 C++ 03スタイルの「テンプレートタイプ定義」を使用してcaller
の最後の2行を置き換えるように変更する必要があることをサポートしていません
typedef typename redi::make_index_Tuple<sizeof...(Args)>::type indices;
caller_impl(func, argtuple, indices());
同様のユーティリティがC++ 14でstd::index_sequence
として標準化されました(スタンドアロンC++ 11実装については index_seq.h を参照)。