C++/C++11 - Switch statement for variadic templates?

假装没事ソ 提交于 2019-11-28 04:11:45

You can use an array to bridge compile-time and runtime: (ab)use variadic templates to statically initialize the array elements, and then index into the array with the runtime parameter. The tricky part is finding the right element type for the array. In addition since we need the template to be variadic on the tuple indices rather than on the tuple elements I'll be using my usual trick.

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{});
}

Hmmm, I'm tempted to try something like this:

template<int N, typename ...Args>
struct call_N_helper
{
  static void call(const std::tuple<Args...> & t, int i)
  {
    if (i == N) std::get<N>(t).call();
    else call_N_helper<N-1, Args...>(t, i);
  }
};

template<typename ...Args>
struct call_N_helper<0, Args...>
{
  static void call(const std::tuple<Args...> & t, int i)
  {
    if (i == 0) std::get<0>(t).call();
  }
};

template<typename ...Args>
void call_N(const std::tuple<Args...> & t, int i)
{
  call_N_helper<sizeof...(Args), Args...>::call(t, i);
}

This is just an idea, untested and all.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!