模板函数名称作为模板参数?

时间:2014-03-22 20:06:07

标签: c++ templates c++11 metaprogramming

我定义了一些模板函数,如:

template<unsigned char V>
void print(){
    std::cout << (int)V << std::endl;
}

现在我想要创建函数指针的const数组。我尝试使用C ++ 11可变参数模板来构造这些数组:

template<typename Type, Type... args>
struct Combination{
    const static Type data[sizeof...(args)];
};

template<typename Type, Type... args>
const Type Combination<Type, args...>::data[sizeof...(args)] = {args...};

template<typename Type, unsigned char var, Type... args>
struct FunArray{
    typedef
    typename FunArray<Type, var-1, &print<var-1>, args...>::result
        result;
};

template<typename Type, Type... args>
struct FunArray<Type, (unsigned char)0, args...>{
    typedef Combination<Type, args...> result;
};

解决方案非常有效。

int main(){
    for(int i = 0; i < 8; ++i)
        FunArray<void(*)(), 8>::result::data[i]();
}

主函数将打印0到7的列表。

现在我的问题是,我有一些其他模板功能,我想编写一组模板工具来为这些函数生成一个数组。所以我需要使用一个参数来替换模板中的硬编码函数名。但是,以下代码将无法编译:

template<typename Type, Type... args>
struct Combination{
    const static Type data[sizeof...(args)];
};

template<typename Type, Type... args>
const Type Combination<Type, args...>::data[sizeof...(args)] = {args...};

template<typename Type, typename Fun, unsigned char var, Type... args>
struct FunArray{
    typedef
    typename FunArray<Type, Fun, var-1, &Fun<var-1>, args...>::result
        result;
};

template<typename Type, typename Fun, Type... args>
struct FunArray<Type, Fun, (unsigned char)0, args...>{
    typedef Combination<Type, args...> result;
};

我该怎么做?谢谢!

1 个答案:

答案 0 :(得分:1)

这应该这样做。诀窍是(a)使用struct template wrappers(printotherPrint)而不是直接函数模板,以及(b)使用模板模板参数。 (我必须承认,我发现C ++ 11的某些限制非常违反直觉,例如,在FunArray的模板参数中使用模板别名会很不错。)

template<unsigned char V>                                                       
struct print{                                                                   
  static void call () { std::cout << (int)V << std::endl; }                     
};                                                                              

template<unsigned char V>                                                       
struct otherPrint{                                                              
  static void call () { std::cout << (char)('a'+V) << std::endl; }              
};                                                                              

template<typename Type, Type... args>                                           
struct Combination{                                                             
  const static Type data[sizeof...(args)];                                      
};                                                                              

template<typename Type, Type... args>                                           
const Type Combination<Type, args...>::data[sizeof...(args)] = {args...};       

template<typename Type, template<unsigned char V> class Fun,                    
         unsigned char var, Type... args>                                       
struct FunArray{                                                                
    typedef                                                                     
    typename FunArray<Type, Fun, var-1, Fun<var-1>::call, args...>::result      
    result;                                                                     
};                                                                              

template<typename Type, template<unsigned char V> class Fun, Type... args>      
struct FunArray<Type, Fun, (unsigned char)0, args...>{                          
  typedef Combination<Type, args...> result;                                    
};

int main() {                                                                    
  for(int i = 0; i < 8; ++i)                                                    
    FunArray<void(*)(), print, 8>::result::data[i]();                           
  for(int i = 0; i < 8; ++i)                                                    
    FunArray<void(*)(), otherPrint, 8>::result::data[i]();                      
  return 0;                                                                     
}