C ++标准库头可以包含C标准头吗?

问题描述 投票:14回答:3

我只能在标准草案N4582中找到

[res.on.headers / 1] C ++标头可能包含其他C ++标头。

似乎没有指定C ++标头是否可以包含C标准标头。

如果允许,即使不包含此标头,使用C标准头中定义的全局名称是否不安全(因为程序可能通过某些C ++标准头隐式包含头)?

c++ c c++-standard-library
3个回答
4
投票

对于你跟进的问题(名称冲突),是的,它当然可以。原因是C ++标准库包含用于C标准库内容的<c:::> C ++标头,并且该标准明确允许它们在全局命名空间中提供名称(除了强制在::std中提供它们)。

此外,根据C ++标准的附录D [depr],C标准库头文件(<:::.h>版本)也是C ++标准库的一部分(尽管已弃用)。这意味着[res.on.headers] / 1允许C ++标头包含它们。


4
投票

C ++标准的D.3 C standard library headers部分使26 C标准头部成为C ++的一部分。因此,这些是C ++的一部分。此外,许多其他C标头都遵循语言的共享子集(可能通过#ifdefing一些东西),使它们成为有效的C和C ++标头。


0
投票

我的答案来得晚,但增加了其他人没有的东西,所以这里......

简短回答:标准是否允许标准C ++标头包含标准C标头仍然不清楚。

其他答案已正确观察到C ++标准

  • 允许标准的C ++标头
  • 包括标准C ++标头。

目前尚不清楚的是标准C头是否是标准C ++头。我可以两种方式提供证据。

为什么C头确实是C ++头

在带有GNU标准C库2.24的GCC 6.24上,以下测试无法编译。

#include <iostream>

namespace {
    const int printf {42};
}

int main()
{
    std::cout << printf << "\n";
    return 0;
}

编译器抱怨说,“对'printf'的引用是模糊的,”尽管测试缺乏明确的#include <cstdio>

主要编译器和标准库(如GCC和GNU)的开发人员的判断很难被忽略。

其他答案进一步说明了我不需要在此重复的原因。

为什么C头不是C ++头

脚注166的C ++ 17标准(草案here)内容如下:

[C] C库设施的C ++头文件可以...定义全局命名空间中的名称。

如果C标题是C ++标题,那么编写这样一个脚注是一种奇怪的方式,不是吗?相反,我们可以预期脚注会以“C库设施的非<*.h> C ++标题......”开头。

最后一个观察结果尚无定论,但在[res.on.headers]中,该标准还包括:

C标准库头只应包含其对应的C ++标准库头....

同样,如果在编写单词的人的估计中C头是C ++头,那么编写它们似乎是一种奇怪的方式。

结论:含糊不清

不幸的是,像其他回答者一样,我无法在标准的某种方式中找到明确的答案。与其他回答者不同,我会得出结论,答案仍然含糊不清。标准中的相关部分包括[contents],[res.on.headers]和[depr.c.headers]。

意见

如果您想知道哪种替代方案在我看来具有优势证据,那么我倾向于不同意其他答案。由于引用的原因,我倾向于说标准不允许标准C ++头包含标准C头。无论如何,这种包含与普通的C ++使用相矛盾,因为这种包含使得匿名全局命名空间更难以使用。 [在我的测试中将printf更改为foo,然后询问如果未来的标准C库添加了函数foo()会发生什么。这样的实验说明了麻烦。]

另一方面,打一个人的工具链是没有意义的,不是吗?在C ++的未来版本澄清之前,我的意思是避免在包含标准库头的源文件中使用匿名全局命名空间。

我怀疑,由于标准已经弃用了使用标准C头的旧样式,标准委员会可能不会过于考虑如何在此期间修补旧样式的问题。也许C ++ 20模块可以提供一个简洁的解决方案。我们会看到。

© www.soinside.com 2019 - 2024. All rights reserved.