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

时间:2017-06-22 08:49:29

标签: c++ gcc namespaces

当我在C ++中使用标准C头时,我通常更喜欢将标识符放入std命名空间的表单,例如<cstdlib>。但是,当我使用它们时,GCC还将名称放入全局命名空间,这意味着它将接受如下程序:

#include <cstddef>

std::size_t x;
size_t y;

int main() {}

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

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

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

-std=c++17 -pedantic -Wall -Wextra -Wpedantic -Weffc++

这些似乎都没有阻止GCC接受非便携式表格。

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

  

C兼容性标头

     

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

     

除了complex.h之外,C ++中包含的每个xxx.h标头   标准库在全局命名空间中放置每个名称   相应的cxxx标题将放在std命名空间中。

     

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

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

3 个答案:

答案 0 :(得分:3)

不幸的是,这些标头还必须定义相应c标头中的所有类型。

  

18.4.1标题提要 [cstdint.syn]

     

2标题定义所有类型和宏与C标准库标题<stdint.h>相同。

答案 1 :(得分:3)

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

回到C ++ 98,不允许那些标题添加到另一个名称空间。有些编译器无法做到这一点。例如,如果C ++库编写者不控制C头,那么通常的实现技术是将C ++头部#include改为C头,并使用声明将C名称提升为std。 。所以规则被改变以反映现实。

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

简而言之,您不能依靠#include <cxxx>将C名称放入全局命名空间,但您也无法依靠它而不是将它们放在那里。

答案 2 :(得分:0)

  

但如果我想要我的代码,应该拒绝y的声明   便携

请放心,您的代码将是可移植的:但遗憾的是,如果没有std::size_t,则无法获取size_t。这是因为#include <cstddef>需要引入<stdint.h>中定义的C类型。

因为你无法定义&#34; C ++中的一种类型,你唯一的办法是使用静态分析工具:然后你可以强制执行任何惹人喜爱的风格规则。