コンパイル時整数列


概要

C++11で可変長テンプレート機能が追加されている。この機能を用いることで、 以下のようにパラメータの詳細を機にすることなく、他の関数へ転送することができるようになった。 この時、tはパラメータパックであり、t...とすることでパック展開を行うことができる。

template <class... T>
void f(T... t) {        //tは関数パラメータパック
    expr(t...);         //パック展開
}

ここで、以下に示すようなパラメータパックが他の型の一部であるような場合、引数はパラメータパックとして扱われない。 ゆえに、前述の例のように直接的にパック展開を行うことができない。

template <class... T>
void f(std::tuple<T...> t);

この例のようにタプルを展開させるためには、関数を再帰的に呼びさして一つずつ展開させる必要があった。 これを簡単化させるために、コンパイル時整数列の機能が追加された。

template <int...> struct index_sequence;

上記のようなテンプレートクラスで表現され、テンプレート引数が<0, 3="" 1,="" 2,="">となるような型が生成される。 このクラスの生成用にヘルパクラスが定義されており、make_index_sequenceテンプレートクラスを用いる。 これのテンプレート引数に生成したい個数の数を指定することで、0, 1, ..., Nまでの整数列が生成される。

これらを用いることで、タプルの展開を以下のように簡略化できる。

template <typename Tuple, size_t... I>
voud f(Tuple t, index_sequence<I...>)
{
    expr(std::get<I>(t)...);
    //以下のように展開される
    //expr(std::get<0>(t), std::get<1)(t), ...
}

template <typename Tuple,
          typename Indices = make_index_sequence<std::tuple_size<Tuple>::value>>
void tuple_expand(Tuple args) {
    f(tuple, Indices());
}

また、arrayからtupleへの変換も直感的に実現できる。

template <typename Array, size_t ...I>
auto a2t_(const Array& a, index_sequence<I...>)
 -> decltype(std::make_tuple(a[I]...))
{
    return std::make_tuple(a[I]...);    //std::make_tuple(a[0], a[1], ...)
}

template <typename Array, size_t N, typename Indices = make_index_sequence<N>>
auto a2t(const Array& a, index_sequence<I...>)
 -> decltype(a2t_(a, Indices()))
{
    return a2t_(a, Indices());
}

results matching ""

    No results matching ""