【问题标题】:recursive template instantiation exceeded maximum depth of 256递归模板实例化超过最大深度 256
【发布时间】:2014-05-13 01:47:37
【问题描述】:

我试图使用 constexpr 函数重写 Factorial 实现,但由于某种原因,我不知道为什么会出现编译错误:

递归模板实例化超过最大深度 256

实际上我知道错误消息的含义,但我不知道为什么我会收到此错误以及为什么使用 struct 的代码 1 工作但第二个 using 函数不起作用。它们有什么区别?

 // yes, I know it doesn't return the factorial value. First I want to make it compile
template <int N>
constexpr int f2()
{
    return N == 0 ? 1 : f2<N - 1>();
}

template <int N> struct Factorial
{
    enum 
    {
        value = N * Factorial<N - 1>::value
    };
};

template <> struct Factorial<0>
{
    enum
    {
        value = 1
    };
};


int main() 
{
    x = f2<4>(); // compile error
    n = Factorial<4>::value; // works fine
}

【问题讨论】:

  • 你为什么在模板中使用 constexpr?为什么不直接传入 N 作为参数呢?为这种事情摆脱 f 模板是我们拥有 constexpr iirc 的原因之一。
  • @KitsuneYMG 同意这是我在回答中指出的
  • @KitsuneYMG:因为对于我正在编写的函数,我需要告诉编译器参数是常量,constconstexpr 都不是(我需要的方式)所以我需要使用模板参数代替。类似于 Nawaz 的回答:stackoverflow.com/questions/9789913/…

标签: c++ templates c++11 recursion clang


【解决方案1】:

N == 0 时,编译器仍然必须实例化f2&lt;-1&gt;,因为代码中存在函数调用。当f&lt;-1&gt; 被实例化时,f&lt;-2&gt; 被实例化等等。一次又一次地应用此语句,编译器将继续遍历模板,直到超过最大深度。

【讨论】:

    【解决方案2】:

    您需要定义模板函数的特化以在编译时而不是运行时停止递归,就像您的结构版本所做的那样。

    template <int N>
    int f2()
    {
        return N * f2<N - 1>();
    }
    
    template <>
    int f2<0>()
    {
        return 1;
    }
    

    【讨论】:

      【解决方案3】:

      你需要一个像下面这样的停止状态:

      template <>
      int f2<0>()
      {
         return 0;
      }
      

      因为f2&lt;N - 1&gt;() 必须被实例化,所以在你的其他情况下你有你的停止状态:

      template <> struct Factorial<0>
      

      但是,如果您使用的是constexpr,则根本不需要使用模板,因为重点是它将在编译时完成,所以把它变成这样:

      constexpr int f2(int n)
      {
        return n == 0 ? 1 : (n * f2(n-1));
      }
      

      【讨论】:

      • 非常感谢。我不知道(我对 C++ 有点陌生)
      • (我在 cmets 中回答了我为什么使用模板)
      猜你喜欢
      • 2017-01-03
      • 2014-06-15
      • 1970-01-01
      • 2017-11-05
      • 2013-11-30
      • 2020-12-13
      • 2013-03-03
      • 2016-07-09
      • 2015-08-14
      相关资源
      最近更新 更多