8 c++ header-files language-lawyer unspecified-behavior
有一个声明,C++标准库中的哪些标头保证包含另一个标头?:
C++标准库头可以以未指定的方式彼此包含,因此程序员通常不应该依赖于包括另一个的一个头.[...]
在实践中,情况往往如此.例如,<iostream>可能包括<string>,在其他情况下,您需要<string>明确包含.但是,我似乎无法在N4140中找到这种情况.我查了一下:
我能找到的最近的是来自[using.headers]:
2翻译单元可以包括任何顺序的图书馆标题(第2条).每个可以被包括不止一次,除了每次包含
<cassert>或<assert.h>依赖于NDEBUG的词法当前定义的效果之外,没有任何效果与仅包括一次有效.178
但这似乎适用于C++程序,而不是标准库:
[using.overview]/1本节介绍C++程序如何访问C++标准库的工具.[...]
和[res.on.headers]一样:
1 C++标头可能包含其他C++标头.C++标头应提供其概要中出现的声明和定义.在其概要中显示的包含其他C++头的C++头应提供出现在那些其他头的概要中的声明和定义.
我认为关键是第一句话,但它没有明确说明它是未指明的行为.它是否在任何地方声明这是未指明的行为还是只是暗示?
鉴于 [res.on.headers] 在 C++14 标准中找到
17 图书馆简介
17.6 图书馆范围内的要求
17.6.5 符合要求的实现
17.6.5.2 标头
似乎可以肯定地说,本段中的“C++ 头文件”是指 C++ 标准库头文件。该术语应被理解为与 C 标头(即,从 C 标准库中培养出来的那些货物)相反,后者在这方面不太自由。[res.on.headers] 是这样描述它们的:
C 标准头文件(D.5)应仅包括其相应的 C++ 标准头文件,如 17.6.1.2 中所述。
由于一个C++标准库头文件可能包含其他C++标准库头文件,因此任何其他标准库头文件的内容可能在包含另一个头文件后才被知道,但是除非声明一个头文件必须包含另一个头文件,否则这是不可靠的。一个标头是否必须包含另一个标头是逐个标头定义的。例如,<iostream>[iostream.objects.overview] (27.4.1) 中说:
标题
<iostream>概要Run Code Online (Sandbox Code Playgroud)#include <ios> #include <streambuf> #include <istream> #include <ostream> (...)
并在 [template.bitset] (20.7)
标题
<bitset>概要Run Code Online (Sandbox Code Playgroud)#include <string> #include <iosfwd> // for istream, ostream (...)