C库设施标头的命名空间注入不一致
Inconsistent namespace injection for C library facilities headers
当我遇到这个"问题"时,我正在玩ptrdiff_t
并阅读C++11标准。首先,事实:
类型ptrdiff_t
(只是一个示例)从标准C库头<stddef.h>
拉入<cstddef>
(§18.2/2)。第17.6.1.2节告诉我们,从C标准库拉入的声明将在std
名称空间内:
然而,在C++标准库中,声明(在C中定义为宏的名称除外)在命名空间
std
的命名空间范围(3.3.6)内。是的未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明(7.3.3)注入命名空间std
正如它所说,声明可能首先在全局命名空间中声明,然后注入到std
中。因此,对于我的实现来说,以下编译得很好是有意义的:
#include <cstddef>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
我的实现(gcc 4.6.3)必须在全局命名空间中声明了ptrdiff_t
,然后将其注入到std
中。然而,如果我编译以下代码,我会得到一个错误(注意<iostream>
包含):
#include <iostream>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
main.cpp:在函数"int main(int,const char**)"中:
main.cpp:6:3:错误:"ptrdiff_t"未在此范围内声明
main。cpp:6:3:注意:建议的替代方案:
/usr/include/c++/4.6/i686-linux-gnu/./bits/c++config.h:156:28:注意:"std::ptrdiff_t">
因此,由于std::ptrdiff_t
可用,因此<iostream>
必须以某种方式包含<cstddef>
(尽管不需要)。但为什么全球版本不可用是以前吗?我能不能不期望这种注入是一致的,即使它实际上是同一个头部?这似乎是一种奇怪的行为。注射是否发生可能尚未明确,但至少应该是一种方式或另一种方式,而不是两者都有,对吧?
不要依赖一个标头包括另一个标头,如果您想要在特定标头中声明/定义某些内容,则必须包括它。
对于您给出的例子,对于g++,实际上有两个ptrdiff_t
(和size_t
)的定义。第一个,在namespace std
中,它来自<bits/c++config.h>
。以及来自<stddef.h>
的全局命名空间中的一个(因此也是<cstddef>
)。
问题是您没有使用正确的标头。你应该做
#include <cstddef>
相反。但是您使用
#include<iostream>
它间接地定义了"std::ptrdiff_t"。但是,全局"::ptrdiff_t"并没有在"iostream"中定义,"iostream"也没有像您想象的那样包括"cstdef"。相反,"iostream"确实包含"bits/c++config.h"。实际的"std::ptrdiff_t"在该文件中定义。
如果你查看文件"cstdef"的内容,你会发现那里只有两行"有用"的
顺便说一句,上述讨论适用于GCC 4.6和GCC 4.7。对于GCC 4.4,"iostream"直接包含"cstdef",因此ptrdiff_t将在两个命名空间(std和global)中都可用。#包括#包括
后一行引入了全局"::ptrdiff_t",前一行定义了std名称空间一。
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- CUDA内核和数学函数的显式命名空间
- 嵌套的匿名命名空间
- CMakeLists.txt中的命名空间表示法
- 类是C++中的命名空间吗
- 在命名空间中使用全局命名空间中的函数
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 是否可以将函数导入命名空间,但不能导出它?
- 为什么在这种特殊情况下不需要将 std::hash() 的专用化注入到 std 命名空间中?
- 作用域中定义的变量与注入该作用域的命名空间变量
- 自定义点 - 命名空间注入
- C库设施标头的命名空间注入不一致
- 将实验命名空间注入 std
- 如果在全局命名空间中的类中引入一个朋友,则该朋友将被全局注入