我可以停止 GCC 将标准库名称包含到全局命名空间中吗?

Tob*_*ght 5 c++ gcc namespaces

当我在 C++ 中使用标准 C 头文件时,我通常更喜欢将标识符放入std命名空间的形式,例如<cstdlib>. 但是,当我使用这些时,GCC 也会将名称放入全局命名空间中,这意味着它会接受这样的程序:

#include <cstddef>

std::size_t x;
size_t y;

int main() {}
Run Code Online (Sandbox Code Playgroud)

在这里,声明x是正确的,但是y如果我希望我的代码是可移植的,应该拒绝声明。(请注意,如果我包含<stddef.h>而不是<cstddef>,GCC正确拒绝 的声明x)。

我可以让 GCC 拒绝上述声明y吗?

我编译了所有我能想到的迂腐和警告:

-std=c++17 -pedantic -Wall -Wextra -Wpedantic -Weffc++
Run Code Online (Sandbox Code Playgroud)

这些似乎都没有阻止 GCC 接受不可移植的形式。


我现在不确定我是否正确理解了规则;我的知识来自 CPP 参考中的这一部分:

C 兼容性头文件

对于某些形式的 C 标准库头文件xxx.h,C++ 标准库都包括一个同名的头文件和另一个形式的头文件cxxx

除了complex.hxxx.hC++ 标准库中包含的每个标cxxx头都将相应标头放置在std命名空间中的每个名称都放在全局命名空间中。

允许这些头文件在std 命名空间中也声明相同的名称,相应的cxxx头文件也允许在全局命名空间中声明相同的名称:包括<cstdlib> 绝对提供std::malloc和也可能提供::malloc。包括<stdlib.h>肯定提供::malloc和也可能提供 std::malloc。这甚至适用于不属于 C 标准库的函数和函数重载。

对我来说,最后一段表明 GCC 的行为是允许的,但不是必需的,因此依赖它是错误的。

Pet*_*ker 3

规则是#include <xxx.h>(其中xxx.h是标准 C 标头的名称)需要在全局命名空间中定义 C 标准所需的该标头的所有名称,并且还允许在命名空间std。类似地,#include <cxxx>(其中cxxx是标准 C 库的标准 C++ 头文件之一的名称) 需要定义命名空间中相应 C 头文件(具有相同含义)的所有名称std,并且还允许定义这些名称在全局命名空间中。

早在 C++ 98 中,这些标头不允许将名称添加到其他命名空间。有些编译器无法做到这一点。例如,如果 C++ 库编写者不控制 C 标头,则通常的实现技术是将 C++ 标头添加到#includeC 标头,并将 C 名称提升到stdusing 声明中。因此规则被改变以反映现实。

语言定义不要求这些标头将名称放在两个位置;如果是这样,那么就cxxx不需要标题了。

简而言之,您不能指望#include <cxxx>将 C 名称放入全局名称空间,但也不能指望它不将它们放在那里。