`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
将代表不同的类型。