创建一系列显式函数模板实例化

时间:2016-10-26 14:59:57

标签: c++ templates variadic-templates

在C ++ 11中,我可以构建一个模板,该模板将一系列函数模板显式实例化为数组初始化器吗?我想要实现的目标(请不要问我为什么需要它,因为这是一个长篇故事)看起来像

// The template I want to instantiate:
template<size_t N> void callbackTemplate(const int dummy) {
    // Do something which needs to know 'N'.
}

// The variable I want to assign 'callbackTemplate' instantiations to:
void (*callback)(const int dummy);  // This cannot be std::function, because it 
                                    // is not defined by me! It is already there and 
                                    // must be used as it is.

// This is the set of instantiations I want to prepare:
std::array<decltype(callback), 3> callbackTemplates = {
    callbackTemplate<0>, callbackTemplate<1>, callbackTemplate<2>
};

上面的代码按原样运行。我想要改变的是callbackTemplates数组的初始化。我希望初始化器成为一个依赖于编译时常量的模板,并创建实例化0..N。

问题在某种程度上与C++ static const array initialization in template class有关,但我没有设法&#34; templatise&#34;另一个模板的实例化。

3 个答案:

答案 0 :(得分:2)

您可以使用C ++ 14 std::integer_sequence的实现来完成此操作。 Here是一个。

callback_t定义为

using callback_t = decltype (callback);

你可以传递一个序列并使用类型推导:

template<unsigned... Is>
array<callback_t, sizeof...(Is)> make_callback_array_impl(seq<Is...>)
{
    return { callbackTemplate<Is>... };
}

template<unsigned N>
array<callback_t, N> make_callback_array()
{
    return make_callback_array_impl(GenSeq<N>{});
}

live demo

答案 1 :(得分:2)

这可以通过变量模板特化来完成。

template<class>
int callbackTemplates_v;

template<std::size_t... Indicies>
std::array<decltype(callback), sizeof...(Indicies)>
  callbackTemplates_v<std::index_sequence<Indicies...>> = {callbackTemplate<Indicies>...};

template<std::size_t N>
auto callbackTemplates = callbackTemplates_v<std::make_index_sequence<N>>;

现在callbackTemplates<N>是来自N callbackTemplate 0..N-1的{​​{1}}个数组。

答案 2 :(得分:0)

你的意思是如下吗?

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 <std::size_t N>
struct arrayWrapper
 {
   private:
      std::array<decltype(callback), N>  callBT;

      template <std::size_t ... rng>
      arrayWrapper (const range<rng...> &)
         : callBT{ callbackTemplate<rng>... }
       { }

   public:
      arrayWrapper () 
         : arrayWrapper (typename rangeH<N>::type())
       { }
 };

如果您可以使用C ++ 14,则可以丢弃rangeHrange,并且包装器变得简单

template <std::size_t N>
struct arrayWrapper
 {
   private:
      std::array<decltype(callback), N>  callBT;

      template <std::size_t ... rng>
      arrayWrapper (const std::index_sequence<rng...> &)
         : callBT{ callbackTemplate<rng>... }
       { }

   public:
      arrayWrapper () 
         : arrayWrapper (std::make_index_sequence<N>())
       { }
 };