【问题标题】:template with one explicit argument带有一个显式参数的模板
【发布时间】:2016-09-28 15:58:03
【问题描述】:

我尝试在元编程的阶乘示例中添加另一个模板参数。但以下不起作用。正确的方法是什么?

代码:

#include <iostream>

template <typename T, int Depth>
inline void loop(T i){
    std::cout << i;
    loop<T, Depth-1>(i - 1);
}
template <typename T, int Depth>
inline void loop<T, 0>(T i){
    std::cout << i << std::endl;
}

int main(void){
    int i = 10;
    loop<int, 3>(i);
}

错误:

test4.cpp(9): error: an explicit template argument list is not allowed on this declaration
  inline void loop<T, 0>(T i){

【问题讨论】:

    标签: c++ templates metaprogramming template-meta-programming


    【解决方案1】:

    您不能部分专门化函数模板。句号。

    在 C++17 中,您将能够编写:

    template <typename T, int Depth>
    inline void loop(T i){
        std::cout << i;
        if constexpr (Depth > 0) {
            loop<T, Depth-1>(i - 1);
        }
    }
    

    在那之前,我建议将深度作为integral_constant 参数:

    template <typename T>
    inline void loop(T i, std::integral_constant<int, 0> ) {
        std::cout << i << std::endl;
    }
    
    template <typename T, int Depth>
    inline void loop(T i, std::integral_constant<int, Depth> ){
        std::cout << i;
        loop(i - 1, std::integral_constant<int, Depth-1>{} );
    }
    

    【讨论】:

    • 如何调用该循环?我的意思是 main 函数应该是什么样的?
    • 如果我使用int main(void){ int i = 10; loop(i, std::integral_constant&lt;int, 3&gt;{} ); } 并使用 g++ -std=c++14 进行编译,则会出错。错误是模板实例化深度超过 900。
    【解决方案2】:

    您可以使用辅助类及其特化来完成实际工作。

    template <typename T, int Depth> struct LoopHelper
    {
       static void doit(T i)
       {
          std::cout << i;
          LoopHelper<T, Depth-1>::doit(i);
       }
    };
    
    template <typename T> struct LoopHelper<T,0>
    {
       static void doit(T i)
       {
          std::cout << i;
       }
    };
    
    
    template <typename T, int Depth>
    inline void loop(T i){
       LoopHelper<T, Depth>::doit(i);
    }
    

    额外细化

    我建议更改loop 以允许扣除T

    template <int Depth, typename T>
    inline void loop(T i){
       LoopHelper<T, Depth>::doit(i);
    }
    

    然后,你可以使用:

    int i = 10;
    loop<3>(i);
    

    并让T 推导出为int

    【讨论】:

    • @rxu,是的,确实如此。我在发布答案之前对其进行了测试。
    猜你喜欢
    • 2014-09-08
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    相关资源
    最近更新 更多