【问题标题】:template function name as template parameter?模板函数名称作为模板参数?
【发布时间】:2014-03-22 20:06:06
【问题描述】:

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

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

我该怎么做?谢谢!

【问题讨论】:

  • 您可以使用函数对象类型而不是函数。 C++ 中有模板 template-parameters(= 传递模板),但仅适用于类模板,不适用于函数模板(您不能直接将名称作为模板参数传递)。
  • 另一种方法是传递具有静态成员函数模板的函数对象类型(作为类型模板参数的参数)。那么你就不用处理模板template-parameters了,但是需要使用template关键字进行语法消歧。

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


【解决方案1】:

应该这样做。诀窍是 (a) 使用结构模板包装器(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;                                                                     
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多