これは、いくつかのインデックス機構を使用して非常に簡単に行うことができます。gen_seq
コンパイル時の整数シーケンス (seq
クラス テンプレートによってカプセル化)を生成するためのメタ関数が与えられた場合:
namespace detail
{
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { };
}
そして、次の関数テンプレート:
#include <tuple>
namespace detail
{
template<typename T, typename F, int... Is>
void for_each(T&& t, F f, seq<Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
}
template<typename... Ts, typename F>
void for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, detail::gen_seq<sizeof...(Ts)>());
}
for_each_in_tuple
上記の関数は次のように使用できます。
#include <string>
#include <iostream>
struct my_functor
{
template<typename T>
void operator () (T&& t)
{
std::cout << t << std::endl;
}
};
int main()
{
std::tuple<int, double, std::string> t(42, 3.14, "Hello World!");
for_each_in_tuple(t, my_functor());
}
これが実際の例です。
具体的な状況では、これを使用する方法は次のとおりです。
template<typename... Ts>
struct TupleOfVectors
{
std::tuple<std::vector<Ts>...> t;
void do_something_to_each_vec()
{
for_each_in_tuple(t, tuple_vector_functor());
}
struct tuple_vector_functor
{
template<typename T>
void operator () (T const &v)
{
// Do something on the argument vector...
}
};
};
繰り返しになりますが、これは実際の例です。
アップデート
C++14以降を使用している場合は、上記のクラスseq
とgen_seq
クラスを次のstd::integer_sequence
ように置き換えることができます。
namespace detail
{
template<typename T, typename F, int... Is>
void
for_each(T&& t, F f, std::integer_sequence<int, Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
} // namespace detail
template<typename... Ts, typename F>
void
for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, std::make_integer_sequence<int, sizeof...(Ts)>());
}
C++17以降を使用している場合は、これを行うことができます (以下のこのコメントから):
std::apply([](auto ...x){std::make_tuple(some_function(x)...);} , the_tuple);