我如何确定 header 在 C++ 中调用另一个 header?

How can I determine what header calls another header in c++?

我正在阅读这里:Can std::string be used without #include <string>?, <iostream> is calling <string>. But I do not see any includes of <string> in Standard library header <iostream> from c++ standard: https://en.cppreference.com/w/cpp/header/iostream。根据该文档,在 <iostream> 中仅包含 <ios><streambuf><istream><ostream>。所以这段代码有效(文件foo.cpp):

#include <iostream>

int main(){
    std::cout << "enter srting\n";
    std::string out; //std::string should not be included according to standard documentation
    std::cin >> out;
    std::cout << "test, " << out;
}

但我必须尝试查看从 gcc:

生成的依赖项
cc -H foo.cpp |& vim -

并且输出是(我有正则表达式输出文件,里面有 string):

. /usr/include/c++/8/iostream
..... /usr/include/c++/8/bits/stringfwd.h
...... /usr/include/c++/8/string
....... /usr/include/c++/8/bits/basic_string.h
........ /usr/include/c++/8/ext/string_conversions.h
....... /usr/include/c++/8/bits/basic_string.tcc

所以我看到最后确实包含了很多“字符串”header

  1. (当 <iostream> 的“包含”列表中未提及 <string> header 时,我应该相信该文档吗?)。

其中一些在 #include stack(gcc 手册中的术语)上更深入,这让我产生疑问,

  1. 什么叫什么?定义 std::string 的“真实”header 是什么? (是/usr/include/c++/8/bits/basic_string.h吗?...)

在这个问题 Why does omission of "#include <string>" only sometimes cause compilation failures? 中,他们提到:

Some compilers on some platforms may on some time of the month compile even though you failed to include the header

但是从上面输出的“字符串header”来看,有多个,编译器怎么可能只编译sometimes?这些 header 中的哪些对于成功编译真的很重要?

  1. 如何在对编译器有意义的 cpp headers 中定位,并且可以跟踪它们的“#include 堆栈”(即其他有意义的 headers)?

编辑: 如果这取决于我对 stdlib++ 的具体实现,那么我想知道如何确定 from source 是否在 before 我尝试编译。不是通过“如果它编译,那么它就可以工作”。

一般来说,您无法知道哪些 header 被您包含的 header 传递包含,并且任何标准 header 都允许但不要求包含任何其他 header。而且你不应该依赖传递包含 ever。您应该包括您使用的东西所需的 headers,然后就可以了。

<iostream> is calling <string>

你的意思是它包括<string>?调用是对函数做的事情。

But I do not see any includes of <string> in Standard library header <iostream> from c++ standard: https://en.cppreference.com/w/cpp/header/iostream.

您正在阅读的是 <iostream> 的文档。事实上,<iostream> 未记录为包含 <string>.

So this code works (file foo.cpp):

它可能适用于某些标准库实现。它可能无法使用其他实现。

  1. (so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).

cppreference 质量相当高。除非它与标准相矛盾,否则可以相当安全地假设它是正确的。确实在这方面是正确的:<iostream> 不保证包含 <string>.

  1. what calls what?

一些 header 包括其他一些 header。没有必要比这更准确地知道,因为你不应该依赖传递包含(除了那些被记录的)。

And what is the "true" header, that define std::string of them?

根据 documentationstd::string 在 header 中定义,命名为 string(通常风格化为 <string>,与传统的包含语法相匹配)。

so how's possible for a compiler to compile only sometimes?

它可以从操作系统询问当前时间,并根据时间使用分支来做一件事或另一件事。编译器通常不会这样做,但关键是他们可以。

更现实地说,您可能在某些时候需要使用另一个(版本)的编译器(或标准库实现)来编译您的程序。不同的实现行为各不相同。

Which of these headers are really important for successful compilation?

记录在案以定义和声明您的程序所依赖的定义和声明的名称。如果您使用 std::string,那么您必须包含定义 std::string 的 header,即 <string>

您应该始终检查您使用的任何符号的文档,并包括指定需要的任何 headers。

C++ 标准仅指定在包含标准 header 时必须提供哪些符号。它不限制其他可用的符号。在您的示例中,标准指定 <iostream> 必须 包括 <ios><streambuf><istream><ostream>,但 <iostream> 可能 包含其作者想要的任何其他 header。它还可以 forward-declare 它可能需要的任何符号。

  1. (so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).

您应该相信当您包含 <string> 时指定为可用的符号将是。就这些。您可能不会假设这些符号在包含任何其他header.

时不会可见
  1. what calls what? And what is the "true" header, that define std::string of them? (is it /usr/include/c++/8/bits/basic_string.h?...)

这是一个实现细节,只能通过检查实现的 header 来回答。 Libstdc++(GCC 使用的标准库实现)在 bit/stringfwd.h 中有 std::string class 的声明,在 bits/basic_string.hbits/basic_string.tcc 中有定义(对于当前版本,至少),但这根本不是必需的。如果 libstdc++ 维护者决定他们想要重构和重组事物,他们可以自由地这样做。 C++ 语言保证的唯一要求是当包含 <string>std::string 必须可用。

But from the upper output of the "string headers", there is multiple of them, so how's possible for a compiler to compile only sometimes?

不同的标准库实现或同一实现的不同版本可以传递地包含不同的 header。不同的编译器标志(即调试标志或不同的标准合规模式)可以传递地包含不同的 headers.

Which of these headers are really important for successful compilation?

  1. How to orient in cpp headers, which are meaningful for compiler, and could be tracked their "#include stack" (i.e. other meaningful headers)?

个个都很有意义。标准库的作者如果不需要 header 就不会包含它。仅仅因为 没有直接使用任何符号 declared/defined 并不意味着 none 被直接使用。


EDIT: If it depends on my specific implementation of my stdlib++, then I want to know how can I determine from source whether that inclusion is made before I try to compile. Not by "If it compiles, then it works".

了解的唯一方法是查看标准库实现的 header。它们没有什么神奇之处;它们只是 C++ 代码。如果您想知道 <iostream> 是否包含 std::string 的声明或定义,请打开您的实施副本 <iostream> 并查找 std::string 的声明或定义。对 <iostream> 包含的任何 header 重复此过程。