【问题标题】:How to determine which header files to include?如何确定要包含哪些头文件?
【发布时间】:2019-11-27 12:28:17
【问题描述】:

假设我有以下(非常简单的)代码。

#include <iostream>
int main() {
    std::cout << std::stoi("12");
}

这在 g++ 和 clang 上都能正常编译;但是,它无法在 MSVC 上编译并出现以下错误:

错误 C2039:“stoi”:不是“std”的成员

错误 C3861:“stoi”:找不到标识符

我知道std::stoi&lt;string&gt; 标头的一部分,这可能是前两个编译器包含在&lt;iostream&gt; 中的一部分,而后者没有。根据C++标准[res.on.headers]

一个 C++ 头文件可能包含其他 C++ 头文件。

对我来说,这基本上说明所有三个编译器都是正确的。

当我的一个学生提交作业时出现此问题,TA 将其标记为未编译;我当然去修了。但是,我想防止以后发生这样的事件。那么,有没有办法确定应该包含哪些头文件,而不是每次都在三个不同的编译器上编译来检查?

我能想到的唯一方法是确保对于每个std 函数调用,都存在适当的包含;但是,如果您有数千行长的现有代码,则搜索起来可能很乏味。是否有更简单/更好的方法来确保交叉编译器的兼容性?

三个编译器的例子:https://godbolt.org/z/kJhS6U

【问题讨论】:

  • 如果您记得std::stoi 用于处理字符串,您可能会猜到&lt;string&gt; 将是一个很好的包含标题。或者你可以搜索a good reference,它会告诉你。而且我建议您始终明确地包含头文件,这样您就不必依赖非可移植实现特定的行为。
  • 最好的方法是在去任何其他平台之前去cppreference。他们那里有非常详细的东西。
  • 在您编写代码时包含适当的标题。 IE。当您编写包含std::stoi 的代码时,您会立即确保#include &lt;string&gt; 也存在。
  • 一般情况下这是difficult problem。然而,当我们谈论缺少标准库包含时,通常的方法确实是检查所有使用的函数调用/类型。
  • @skratchi.at,学生们被告知他们可以使用他们想要的任何编译器,只要他们的代码符合标准。 4 年后,这是第一次成为问题。

标签: c++


【解决方案1】:

是否有更简单/更好的方法来确保交叉编译器的兼容性?

如果你有一个庞大的代码库并且到目前为止还没有这样做,这总是会有点麻烦,但是一旦你修复了你的包含,你可以坚持一个简单的过程:

当您编写使用标准功能(如 std::stoi)的新代码时,将该名称插入 Google,转到 cppreference.com 文章,然后查看顶部以查看其定义在哪个标头中。

如果尚未包含,则将其包含在内。大功告成!

(您可以为此使用标准,但这并不容易。)

不要想像&lt;bits/stdc++.h&gt;一样为了cheap, unportable hacks而放弃一切!


tl;dr:文档

【讨论】:

  • 公平地说,一旦你有效地记住了所有这些并且不需要再查找它,那感觉很流畅
  • @JosephWood:如果您不知道给定函数是死记硬背的,那么您可能应该查看该函数以仔细检查您对它的假设,因此找出它属于哪个标头甚至不需要额外的时间。
  • 像@JosephWood 一样,我也希望那些有更多经验的人有更好的方法。我知道大多数 STL 函数要包含哪些标题,但希望有一种比查找每个函数更简单的方法来教学生:P
  • @ChrisMM 有像include-what-you-use 这样的工具。无法保证它们的正确性(有时确实需要手动工作),但一点也不差。
  • @ChrisMM 教你的学生参考文档是非常非常重要的。每天都有成千上万的人涌入这个网站,他们不知道他们应该这样做。使用文档更简单/更好的方式。
【解决方案2】:

除了查看文档并手动进行(痛苦且耗时)之外,您还可以使用一些工具来为您完成这些工作。

您可以在 Visual Studio 中使用 ReSharper,它能够组织导入(实际上没有 ReSharper 的 VS 不是很实用)。如果缺少包含,建议添加它,如果它已过时,则包含的行以更淡的颜色显示。

或者您可以使用同样具有此功能的 CLion(适用于所有平台)(实际上这是同一制造商的 JetBrains)。

还有一个叫做include what you used的工具,但它的目的是利用前向声明,我从来没有用过(我个人-我的队友为我们的项目做过)。

【讨论】:

  • clion 不自动包含正确的标题,如果其他标题已经包含(即如果已经包含 iostream,则不会在此处建议字符串)IIRC
猜你喜欢
  • 2011-03-27
  • 2011-09-27
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-13
  • 2011-04-14
  • 1970-01-01
相关资源
最近更新 更多