18

我正在编写一个非常简单的模板类,使用元编程来计算编译时的总和,如下所示:

#include <iostream>

using namespace std;

template<int N>
class Sum
{
    public:
        enum {value = N + Sum<N-1>::value };
};

template<>
class Sum<0>
{
    public:
        enum {value = 0};
};


int main()
{
    cout << Sum<501>::value << endl;
}

有趣的是:

  • 当我打印 Sum<500> 及以下时,它工作正常
  • 当涉及 Sum<501> 时,编译失败:

    sum.cpp:9: 从Sum<500>' sum.cpp:9: instantiated fromSum<501>' 实例化 sum.cpp:22: 从这里实例化

    sum.cpp:9:错误:不完整的类型Sum<1>' used in nested name specifier sum.cpp:9: error: enumerator value for值'不是整数常量

  • Sum<501>会报Sum<1>的错误,Sum<502>会报Sum<2>的错误,差总是2,在我看来编译器有500的限制资源。

对此有任何想法吗?他们是打破这个限制的方法吗?

谢谢。

编辑:
谢谢大家,重点不在于算法,而在于编译器的限制——我知道有一种简单的方法可以得到总和:)

编辑2:

  • 使用 gcc 4.6 +,错误信息更有帮助

    sum.cpp:9:14: 错误: 模板实例化深度超过最大值 1024 (使用 -ftemplate-depth= 增加最大值) 实例化'class Sum<1>' sum.cpp:9:14: 从'Sum 递归实例化<1024>' sum.cpp:9:14: 从 'Sum<1025>' 实例化 sum.cpp:22:22: 从这里实例化

所以是的,使用 ftemplate-depth 是正确的方法。但是在 Windows 中呢?VC9.0 的上限是 499,似乎没有设置模板深度的选项,请参见此处

4

2 回答 2

16

如果您使用的是 GCC,则可以使用 设置模板递归深度-ftemplate-depth=X,其中X是所需的深度:

g++ ...... -ftemplate-depth=750

请记住,这不仅仅是您可以任意设置的一些限制。在某些时候,您会遇到操作系统和硬件限制。

关于您的实际 sum 函数,前 N 个正整数的 Sum 有一个众所周知的解析解。

(即n*(n+1)/2

于 2012-09-05T08:59:09.260 回答
15

附录 B 规定了推荐的最低限度;对于递归嵌套模板实例,建议的最小限制为 1024。您的实现似乎有 500 的限制;这仍然是合规的,因为建议的最低限度只是指导方针。

您的编译器可能有一个命令行标志或其他选项来增加其递归嵌套模板实例化限制。

最简单的解决方法是使用非递归算法;在你的情况下,

template<int N>
class Sum
{
    public:
        enum {value = N * (N + 1) / 2 };
};
于 2012-09-05T09:01:08.920 回答