如何将N个函数指针数组初始化为从0..N-1索引的函数模板?

时间:2016-06-21 20:46:20

标签: c++ arrays c++11 initializer-list static-initialization

给定function_sig的函数指针数组,我想将它初始化为一组模板函数指针,这些指针是通过模板参数索引的。这可能吗?

E.g。

template<int I>
void fn() { /* do something */ }

typedef void(*function_sig)();

template<int ARRAY_SIZE>
struct items
{
  static function_sig array[ARRAY_SIZE];
};

template<int ARRAY_SIZE>
function_sig items<ARRAY_SIZE>::array = { /* what do I put here? */ };

那么,我是否可以在初始化列表中添加一些内容,以便将items<ARRAY_SIZE>::array初始化为{ fn<0>, fn<1>, ..., fn<ARRAY_SIZE-1> }

注意:我知道使用预处理器魔术的方法,但我想尝试没有它。目前,我想我将不得不取消数组并将其替换为类似于数组的东西,但这会导致在索引伪数组时搜索O(N),我就是我喜欢不这样做。

2 个答案:

答案 0 :(得分:1)

问题是获得从0到ARRAY_SIZE - 1的可变范围。

我建议在基类array

中转移itemsH的解决方案
#include <iostream>


template <std::size_t ...>
struct range
 { };

template <std::size_t N, std::size_t ... Next>
struct rangeH 
 { using type = typename rangeH<N-1U, N-1U, Next ... >::type; };

template <std::size_t ... Next >
struct rangeH<0U, Next ... >
 { using type = range<Next ... >; };


template<int I>
void fn() { std::cout << "[" << I << "]" << std::endl; }

typedef void(*function_sig)();

template <typename T>
struct itemsH;

template <std::size_t ... RNG>
struct itemsH<range<RNG...>>
 {
   static function_sig array[sizeof...(RNG)];
 };

template<std::size_t ARRAY_SIZE>
struct items : public itemsH<typename rangeH<ARRAY_SIZE>::type>
 { };

template <std::size_t ... RNG>
function_sig itemsH<range<RNG...>>::array[sizeof...(RNG)] = { fn<RNG>... };


int main ()
 {
   items<10>  i_10;

   for ( unsigned ui = 0U ; ui < 10 ; ++ui )
      i_10.array[ui]();

   return 0;
 }

p.s。:我已将ARRAY_SIZE的类型从int更改为size_t;希望不是问题

p.s.2:抱歉我的英语不好。

---编辑:添加了C ++ 14示例---

如果你(当你)可以使用C ++ 14,你可以使用std::index_sequencestd::make_index_sequence,丢掉rangerangeH

示例变为

#include <utility>
#include <iostream>


template<int I>
void fn() { std::cout << "[" << I << "]" << std::endl; }

typedef void(*function_sig)();

template <typename T>
struct itemsH;

template <std::size_t ... RNG>
struct itemsH<std::index_sequence<RNG...>>
 { static function_sig array[sizeof...(RNG)]; };

template<std::size_t ARRAY_SIZE>
struct items : public itemsH<std::make_index_sequence<ARRAY_SIZE>>
 { };

template <std::size_t ... RNG>
function_sig itemsH<std::index_sequence<RNG...>>::array[sizeof...(RNG)]
   = { fn<RNG>... };


int main ()
 {
   items<10>  i_10;

   for ( unsigned ui = 0U ; ui < 10 ; ++ui )
      i_10.array[ui]();

   return 0;
 }

答案 1 :(得分:0)

#include <array>

template<int... Is>
struct int_seq { };

namespace detail {

template<int I, int... Is>
struct make_int_seq : make_int_seq<I - 1, I, Is...> { };

template<int... Is>
struct make_int_seq<0, Is...> {
    using type = int_seq<0, Is...>;
};

} // namespace detail

template<int SizeN>
using make_int_seq = typename detail::make_int_seq<SizeN - 1>::type;

template<int I>
void fn() { /* do something */ }

//typedef void(*function_sig)();
using function_sig = void(*)();

template<int ARRAY_SIZE>
struct items {
    static std::array<function_sig, ARRAY_SIZE> array;
};

template<int... Is>
std::array<function_sig, sizeof...(Is)> create_items_array(int_seq<Is...>) {
    return {{ &fn<Is>... }};
}

template<int ARRAY_SIZE>
std::array<function_sig, ARRAY_SIZE> items<ARRAY_SIZE>::array
  = create_items_array(make_int_seq<ARRAY_SIZE>{});

Online Demo

使用C ++ 14,int_seq等消失了std::integer_sequence等人。