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

时间:2014-04-02 02:10:35

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

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

  

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

实际上我知道错误信息的含义但是我不知道为什么我会收到此错误以及为什么使用struct的代码1工作但第二个使用功能的原因并非如此?吨。它们之间的区别是什么?

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

3 个答案:

答案 0 :(得分:6)

您需要一个停止状态,如下所示:

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

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

template <> struct Factorial<0>

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

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

答案 1 :(得分:4)

N == 0时,编译器仍然必须实例化f2<-1>,因为函数调用存在于代码中。实例化f<-1>时,f<-2>将被实例化,依此类推。一次又一次地应用此语句,编译器将继续通过模板递归,直到它超过最大深度。

答案 2 :(得分:2)

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

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

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