有没有办法知道哪些标头自动包含在C ++中

时间:2016-12-18 23:54:02

标签: c++ clang

这是this的后续问题,即

  

在C ++中,与C不同,标准头文件允许#include其他标准头文件。

有没有办法知道哪些标题是自动包含的,因为可能很难猜出哪些标题是在哪些标题中定义的。

动机:我的作业在我的计算机上编译并正常工作,但TA告诉我它没有编译,需要几个标题(互斥和算法)来编译。我怎么能确定我将来提交的代码是防弹的。

我的编译器没有提供有关隐式声明的任何警告。 我正在使用clang++ -std=c++11来编译我的代码。

4 个答案:

答案 0 :(得分:5)

标准列出了每个标题提供的符号。除此之外没有任何保证,既没有明确使用的符号也没有声明所有符号。您需要为您正在使用的任何名称添加每个标头。你应该依赖间接包含。

从积极的方面来看,标准库中没有任何标准库标题需要额外标题的情况。

答案 1 :(得分:3)

如果您想知道特定头文件提取的其他标头,最简单的方法是仅通过编译器的预处理器阶段运行包含文件,而不是完全编译它。例如,如果您想知道<iostream>引入了什么,请创建一个仅包含:

的文件
#include <iostream>

然后预处理它。对于gcc-E选项仅运行预处理程序,而不编译文件,并将预处理文件转储到标准输出。结果输出以:

开头
# 1 "t.C"

这是我的单行源文件。

# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4

显然,gcc会自动拉入此头文件,无论如何。这可以忽略不计。

# 1 "<command-line>" 2
# 1 "t.C"
# 1 "/usr/include/c++/6.2.1/iostream" 1 3

好的,现在我们终于在我的单行源文件中找到了实际的#include语句。这就是<iostream>所在的位置:

# 36 "/usr/include/c++/6.2.1/iostream" 3

# 37 "/usr/include/c++/6.2.1/iostream" 3

# 1 "/usr/include/c++/6.2.1/x86_64-redhat-linux/bits/c++config.h" 1 3

好的,iostream本身#include这个&#34; c ++ - config.h&#34;头文件,显然是内部编译器头。

如果我继续前进,我可以看到<iostream>引入了<ios><type_traits>,以及stdio.h等C头文件。

编写一个带有头文件的快速小脚本,在预处理阶段运行编译器,并生成一个很好的,格式化的所有头文件列表,并不是很难。

答案 2 :(得分:2)

据我所知,没有办法做你想做的事。

如果您尝试在几个示例平台上编译代码,并且它成功,那么它在任何其他平台上编译的可能性就更大,但没有简单的方法可以确定。

根据我的经验,MinGW C ++标头彼此使用的#include更少。所以MinGW可以成为检查可移植性的实用工具。

答案 3 :(得分:1)

这个问题与Are there tools that help organizing #includes?有相当多的重叠之处,由于需要外部工具/资源,因此后者如今已被视为“题外话”。严格来说,这个问题只是关于查找间接包含的方法,但是目标肯定是相同的。


使用“正确的” include语句的问题很难解决。问题中描述的主要是关于间接包含的:一个标头包含一个特定的符号,但是在另一台具有另一个编译器和另一个标头的计算机上,可能不包含该符号。

一些评论和其他答案建议看似务实但不切实际的方法:

  • 尝试使用另一个编译器:这很脆弱,并且不会告诉您有关可能的第三个编译器的任何信息
  • 阅读随附的标题,以查看它们包含哪些其他标题:。标头的概念正好相反,即不必只需阅读它们,而只是使用它们提供的API
  • 生成预处理程序输出并编写工具以半自动方式解决该问题:不。无论如何,这不会解决不同标题版本的问题。
  • 明确包含要使用的事物所需的标题:这基本上是无法维护的。当您在重构过程中将一个功能从文件移动到另一个文件时,您将永远不知道可以安全地删除其中一个文件,而必须将其中一个文件添加到另一个文件中。

    (而且,当您更改包含内容时,您可能会破坏包含标头的第三方代码,因为每个人都面临着相同的问题...)

所有这些都不能涵盖间接包含并不总是一个问题,但有时是有意的:当您想使用std::vector时,您会#include <vector>,而不是#include <bits/stl_vector.h>,即使后者包含定义...


因此,唯一可行的解​​决方案是依靠支持开发人员的工具。 Are there tools that help organizing #includes?的答案中提到了一些工具,最初,我三年前在comment to the question中提到了CDT,但我认为在这里也值得一提:

Eclipse CDT (C/C++ Development Tooling)

这是一个提供“组织包含”功能的IDE。这些功能在https://www.eclipse.org/community/eclipse_newsletter/2013/october/article3.php的文章中进行了介绍,其中指出了困难和警告(我在上面提到了其中的一些),以及如何在CDT中解决这些问题。

尽管只是在一个非常简单的测试项目中,我已经尝试过了(很久以前)。因此,我可以说它基本上可以工作,但是考虑到任务的复杂性,它带有一个免责声明:它与魔术 close 很近,但是在某些情况下它还是会失败。

C ++不能解析和编译。这句话是正确的,因为我先前在堆栈溢出中的答案之一包含行#define not certainly

本文还指出了另一种工具:

Include What You Use

没有对此进行了尝试,但是它似乎非常活跃。 documentation pages还列出了一些困难和目标。乍一看,它似乎不像CDT那样强大和可配置(当然,它不包含在IDE中),但是有些人可能想尝试一下。