解密 C++ 模板错误消息

Deciphering C++ template error messages

提问人:Jason Baker 提问时间:9/7/2008 最后编辑:MottiJason Baker 更新时间:5/1/2020 访问量:11140

问:

我真的开始理解人们说 C++ 的错误消息在模板方面非常糟糕时是什么意思。我见过像函数与其原型不匹配这样简单的事情的可怕长错误。

有什么技巧可以破译这些错误吗?

编辑:我正在使用gcc和MSVC。他们俩似乎都很可怕。

C++ 模板 编译器错误

评论


答:

17赞 nsanders 9/7/2008 #1

您可以尝试以下工具使事情更加理智:

http://www.bdsoft.com/tools/stlfilt.html

3赞 Leon Timmermans 9/7/2008 #2

某些编译器提供的消息比其他编译器更好。您使用的是什么编译器?话虽如此,它们都非常糟糕。C++0X将解决大部分这个问题(参见概念),但该标准要到2009年才会发布,广泛的支持可能会比这更晚:-(

评论

2赞 artless noise 4/13/2013
-1 它们仍然无法破译;也许不像以前那样难以辨认,但仍然可怕!
0赞 Translunar 9/14/2013
是的,我现在正在为一个而苦苦挣扎。它们实在是太难在视觉上解析了!
2赞 4/15/2014
概念画板没有进入C++11。
1赞 dashesy 6/24/2017
8 年后,概念现在在 C++17 中。他们将如何帮助破译模板错误?
11赞 Bernard 9/7/2008 #3

我肯定做不到。小错误会爆炸成一页又一页的不可读垃圾。通常在清晨,在喝咖啡之前。:(

我唯一的建议是深吸一口气,从顶部开始,尝试解析重要的信息。(我知道,说起来容易做起来难,对吧?

2赞 Andy 9/7/2008 #4

至少在 Visual Studio 中,“输出生成”窗口中提供了更多信息,而不是“错误列表”。我在错误列表状态下遇到了模板错误,“无法将 Foo<int> 转换为 Foo<int>”。在“输出”窗口中的实际错误之后有一些行,帮助我破译了实际问题所在。

5赞 Motti 9/7/2008 #5

正如@nsanders所说,STLFilt 是一个很好的解决方案。一个自家开发的 STLFilt(当你不想去安装 Perl 的麻烦时)是在编辑器中复制错误消息并开始替换部分错误,直到它变得(更)易于管理。

例如

s/std::basic_string<char,std::char_traits<char>,std::allocator<char>>/string/g 

用不那么令人讨厌的术语来说,这意味着:

取代:

std::basic_string<char,std::char_traits<char>,std::allocator<char>>

跟:

string

评论

2赞 breakpoint 5/11/2017
这比听起来更有用。不要对人脑的信息过载限制感到尴尬——人与人之间的差异比他们愿意承认的要小。我们都可以同时匹配大约相同数量的模式——诀窍是逐渐学会匹配更大的模式。
4赞 tom 4/30/2020 #6

尽管这是一个旧帖子,但这可能对偶然发现此帖子的其他人有所帮助。

我遇到了完全相同的问题,就我而言,由于错误太长,甚至无法再打印到屏幕上。因此,我将它们转储到一个文本文件中,并尝试使用文本编辑器进行一些基本搜索,而不是遍历该文件,其中一些可能高达 20 MB(对于错误来说还不错)。大多数错误都会被复制,因为我是并行编译的,所以这是另一个大问题。

由于我对这种方法感到厌倦(而且效率也不是很高),我开发了一个小的辅助程序,我可以直接将其链接到我的编译器工具链中,以便编译器生成的任何输出都可以根据 json 文件中定义的一些规则进行格式化。该程序可以在这里找到: https://github.com/tomrobin-teschner/dotify

有三个基本功能:

  • 如果编译器的当前输出(行)包含某个字符串,则不要打印该输出
  • 仅当某一行包含关键字(可以着色)时,才打印该行
  • 如果涉及模板,请删除<>括号之间的内容并用点替换。例如,将简单地替换为 .MyClass<std::vector<double>, std::array<double, 3>>MyClass<...>

完整的错误消息仍存储在日志文件中(如果需要更详细的信息,可以在以后使用),解析器仅适用于打印到控制台的输出。

调用解析器的命令是

/path/to/program | tee log | /path/to/parser -f /path/to/inputFile.json

/path/to/program是要执行的程序(并且应该从中格式化输出),解析器的位置,-f 标志指定输入文件(JSON 格式),对于非常简单的情况,它可能如下所示:/path/to/parser -f /path/to/inputFile.json

{
  "ignoreCompleteLineIfItContainsSubstring" : [
    "should be suppressed"
  ],
  "ignoreContentBetweenDelimiter" : [
    {
      "startingDelimiter" : "<",
      "endingDelimiter" : ">",
      "replaceContentBy" : "..."
    }
  ],
  "styleLineContainingKeywords" : [
    {
      "keyword" : "error",
      "removeDuplicates" : true,
      "applyStyle" : "onKeyword",
      "color" : "red",
      "style" : "bold"
    }
  ]
}

可以在项目网站上找到选项和解释的完整列表(https://github.com/tomrobin-teschner/dotify)