LoginSignup
1
1

More than 5 years have passed since last update.

Variadic Template 使った場合の型要素に switch 文で実行時アクセスしたい

Last updated at Posted at 2015-03-18

http://stackoverflow.com/questions/7381805/c-c11-switch-statement-for-variadic-templates の日本語要約

Q:

DoSomething メンバ関数を持つ複数のクラスを std::tuple に入れた.
整数 i を用いて std::get(t).DoSomething() とすることでタプル t の i 番目の要素の DoSomething() を呼べる.
ここで i は実行時に決まるとすると, 動的ディスパッチするために

switch(i) {
case 0: get<0>(t).DoSomething(); break;
case 1: get<1>(t).DoSomething(); break;
case 2: get<2>(t).DoSomething(); break;
case 3: get<3>(t).DoSomething(); break;
}

としていたんだけど, 長ったらしくて変更に弱い. マクロで case を展開しても限界がある.
C++11 での良いやり方は?

A:

pack展開して関数ポインタテーブル作っちゃえばいいんだよ. 再帰でテンプレート関数探すとswitchより効率悪いしね.

template<int... Indices>
struct indices {
    typedef indices<Indices..., sizeof...(Indices)> next;
};

template<int N>
struct build_indices {
    typedef typename build_indices<N - 1>::type::next type;
};

template<>
struct build_indices<0> {
    typedef indices<> type;
};

// No need to be variadic on the tuple elements as we don't care about them
// So I'm using perfect forwarding for the tuple
template<typename Tuple, int... Indices>
void
do_something_by_index(Tuple&& tuple, int index, indices<Indices...>)
{
    using std::get;

    typedef void (*element_type)(Tuple&&);
    static constexpr element_type table[] = {
        [](Tuple&& tuple)
        { get<Indices>(std::forward<Tuple>(tuple)).DoSomething(); }
        ...
    };

    table[index](std::forward<Tuple>(tuple));
}

// Proverbial layer of indirection to get the indices
template<typename Tuple>
void
do_something_by_index(Tuple&& tuple, int index)
{
    typedef typename std::decay<Tuple>::type decay_type;
    constexpr auto tuple_size = std::tuple_size<decay_type>::value;
    typedef typename build_indices<tuple_size>::type indices_type;

    do_something_by_index(std::forward<Tuple>(tuple), index, indices_type{});
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1