`cname`和`name.h`中的类型可以是不同的类型?
这个代码标准是否符合?
#include <stdio.h>
#include <cstdio>
int main() {
FILE *f1 = 0;
std::FILE *f2 = f1;
}
说明:标准说[头]:
[...]每个标题cname的内容应与相应标题name.h [...]的内容相同,如同包含一样。 然而,在C ++标准库中,声明[...]在命名空间std的命名空间范围(3.3.6)内。 没有说明这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明(7.3.3)注入命名空间std 。
因此,如果它们没有通过明确的使用声明注入,它们可能是不同的类型? 我不认为“似乎通过包含”这个词组是确定性的,因为另一半的文本明显与这个要求矛盾,要求名称在std名称空间内。
我不相信那段说他们必须是相同的。 它只是对原始(C ++ 98)段落的修订,它说:
每个C头都有一个name.h形式的名称,就好像每个名称放在标准库名字空间中的相应的cname头一样,也放在名字空间std的名字空间范围内,并且后面跟着一个明确的using-声明(7.3.3)
这是困难的,不可能遵循的,因为它与大多数系统上现有的真正的C头相冲突。 因此,在C ++ 11中,文本被更改为您引用的那个。 它允许以其他方式实现它,就像他们在实践中一直做的一样 - 使用现有系统提供的C头文件并将名称导入到名称空间std 。
然而,还有另一段说,无论实现如何执行,标题中的名称都意味着同样的事情:
对于来自标准C库的每个类型T ,类型::T和std::T保留给实现,并且在定义时, ::T应与std::T相同。 ([extern.types],17.6.4.3.4)
是的,这符合标准: FILE*在stdio.h声明,在cstdio声明为std::FILE* ,并且由于您引用的段落,两者是相同的。
(唯一没有说明的是,如果你只包含<cstdio> ,你是否也在全局命名空间中具有相同的FILE* )。
更新:我相信这些类型在鼻子上实际上是相同的,并且每个类型只声明一次,然后通过using声明注入其他名称空间。 唯一没有说明的是哪个先来。 相应的相反标准报价是D.5(2):
每个C头都有一个名称为name.h的名称,就好像名称空间中由相应的cname头放置的每个名称放在全局名称空间范围内一样。 没有指定这些名称是首先在名称空间std的名称空间范围(3.3.6)中声明还是定义的,然后通过显式使用声明(7.3.3)将其注入到全局名称空间作用域中。
基本上,这意味着两种实现是可能的:
“C来了”:
// foo.h
struct Gizmo { /* ... */ };
// cfoo
#include "foo.h"
namespace std { using ::Gizmo; }
“具有C兼容性的C ++:
// cfoo
namespace std
{
struct Gizmo { /* ... */ };
}
// foo.h
#include <cfoo>
using std::Gizmo;
是的,他们可以是不同的类型。 使用C ++类型; C头文件仅用于兼容性。
考虑一下,如上面的答案的评论所表明的那样,C ++头文件被实现为namespace std { #include "stdio.h" } ; 那么::FILE和std::FILE将代表不同的类型。
