読者です 読者をやめる 読者になる 読者になる

C++14 コンパイル時整数シーケンス

C++

N3658 Compile-time integer sequences


C++14では、ヘッダに、コンパイル時整数シーケンスの型が追加されます。

// <utility>
namespace std {
  template<class T, T...> struct integer_sequence;
  template<size_t... I>
  using index_sequence = integer_sequence<size_t, I...>;

  template<class T, T N>
  using make_integer_sequence = integer_sequence<T, see below>;
  template<size_t N>
  using make_index_sequence = make_integer_sequence<size_t, N>;

  template<class... T>
  using index_sequence_for = make_index_sequence<sizeof...(T)>;
}

make_integer_sequenceとすると、integer_sequenceという型が出来上がります。


これは、たとえばタプルを展開するときに使用します。以下は、関数f()に、タプルを展開して引数として渡すapply()関数の実装です。

#include <iostream>
#include <tuple>
#include <utility>

template<typename F, typename Tuple, size_t... I>
auto apply_(F&& f, Tuple&& args, std::index_sequence<I...>)
{
    return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}

template<typename F, typename Tuple,
         typename Indices = std::make_index_sequence<std::tuple_size<Tuple>::value>>
auto apply(F&& f, Tuple&& args)
{
    return apply_(std::forward<F>(f), std::forward<Tuple>(args), Indices());
}

void f(int a, char b, double c)
{
    std::cout << a << std::endl
              << b << std::endl
              << c << std::endl;
}

int main()
{
    apply(f, std::make_tuple(3, 'a', 3.14));
}
3
a
3.14

integer_sequenceの各値を、タプルの添字として使用し、それをタプルの全要素に適用することで、「tuple(3, 'a', 3.14)」を「3, 'a', 3.14」に展開しています。


この提案には、ボレロ村上さん(id:boleros)の貢献によって、「効率に関する考察(Efficiency considerations)」の項が追加されています。詳細は、彼のブログを参照してください。
C++ 標準ライブラリにテンプレート再帰深度のオーダーを定めるべきである - ボレロ村上 - ENiyGmaA Code
ISO C++ Standard - Future Proposals に投稿した - ボレロ村上 - ENiyGmaA Code