【问题标题】:Just introducing myself to TMPing, and came across a quirk刚刚向 TMPing 介绍自己,遇到了一个怪癖
【发布时间】:2010-04-14 14:55:33
【问题描述】:

我只是想学习初学者的语法,以及当我在 VS2008 中编写这段简短的代码时它是如何工作的。下面的代码可以将数字 1 加到 499,但如果我将 1 加到 500,编译器会出错:

fatal error C1001: An internal error has occurred in the compiler.

我只是想知道为什么会这样。编译器可以生成多少代码或其他东西是否有一些限制,对我来说它恰好是一个不错的整数 500?

#include <iostream>
using namespace std;

template < int b >
struct loop {
    enum { sum = loop< b - 1 >::sum + b };
};

template <>
struct loop< 0 > {
    enum { sum = 0 };
};

int main() {
    cout << "Adding the numbers from 1 to 499 = " << loop< 499 >::sum << endl;
    return 0;
}

【问题讨论】:

  • 从错误码判断,是VC++。也许它无法处理所有的递归。请改用 GCC。
  • 使用 Visual Studio 2008

标签: c++ templates metaprogramming c1001


【解决方案1】:

我假设使用 gcc(以及扩展 g++)默认的最大模板递归深度是 500,因为至少在我的机器上,我设法通过(稍微好一点的)警告消息重现了您的问题。编译 loop&lt;500&gt;::sum 工作正常,但尝试编译 loop&lt;501&gt;::sum 失败。

如果您使用 gcc(或 g++),解决方案是使用 -ftemplate-depth-## 编译它(其中 ## 是允许的最大深度)。

例如编译main.cpp,最大模板递归深度为2000

g++ -ftemplate-depth-2000 main.cpp

或者将代码转换成这样:

template < int b >
struct loop {
    enum { sum = (b*(b+1))/2 };
};

(但我承认上面的代码并不能帮助你了解模板元编程)

【讨论】:

  • 是的,我知道那个公式。不过感谢您提供的信息。
【解决方案2】:

VC9 (VS2008) 崩溃,数字 > 499。代码本身是有效的,编译器甚至可以在一定数量的递归实例化后停止编译,给出诊断。然而,Internal Compiler Error(俗称​​ICE)肯定不是一个好的诊断方法。

ICE 始终是编译器的错误。它也可能是由代码中的错误引起的,但如果是这种情况,则编译器无法显示对该错误的正确诊断。如果错误是可重现的,您应该向编译器供应商提交错误报告,以便他们修复错误。

在报告此类错误(此处或其他地方)时,您应该永远提供您使用的确切编译器版本。

【讨论】:

  • @Bill:该死,看来我读得太快了。很抱歉,感谢您指出这一点。我修正了我的答案。
【解决方案3】:

查看输出窗口:

c:\projects\cpptemp3\cpptemp3.cpp(9):
致命错误 C1001:内部错误 发生在编译器中。 (编译器文件“msc1.cpp”,第 1411 行) 要解决此问题,请尝试简化或更改程序 靠近上面列出的位置。

【讨论】:

  • 我不是在寻找一种方法来规避这个问题,因为这不是一个真正的程序。我试图理解为什么问题发生在 500 次递归迭代而不是 400 次。
  • @Justen:您已经在编译器内对模板评估堆栈深度进行了逆向工程。 500,不错的整数。虽然我会选择 512。
猜你喜欢
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多