“cname”和“name.h”中的类型可以是不同的类型吗?

Can types in `cname` and `name.h` be different types?

本文关键字:类型 是不同 cname name      更新时间:2023-10-16

此代码是否符合标准

#include <stdio.h>
#include <cstdio>
int main() {
    FILE *f1 = 0;
    std::FILE *f2 = f1;
}

说明:标准说[标题]:

[...]每个标题cname的内容应与相应标题的内容相同name.h[...],就像包含一样。然而,在C++标准库中,声明 [...] 在命名空间std的命名空间范围 (3.3.6( 内。未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式 using 声明 (7.3.3( 注入命名空间std

因此,如果它们不是通过显式使用声明注入的,它们可能是不同的类型吗?我不认为"好像通过包含"短语是决定性的,因为文本的另一半显然与此要求相矛盾,要求名称位于std命名空间内。

是的,这是符合标准的:FILE*stdio.h 中声明,std::FILE*cstdio 中声明,并且由于您引用的段落,两者是相同的。

(唯一未指定的是,如果您包含 <cstdio> ,您是否在全局命名空间中也具有相同的FILE*


更新:我相信这些类型在鼻子上实际上是相同的,并且每个类型只声明一次,然后通过using声明注入到另一个命名空间。 唯一未指定的是哪一个先出现。相应的相反标准报价是D.5(2(:

每个 C 标头(每个标头都有一个 name.h 形式的名称(的行为就像由相应的 cname 标头放置在标准库命名空间中的每个名称都放置在全局命名空间范围内一样。未指定这些名称是首先在命名空间 std 的命名空间范围 (3.3.6( 内声明或定义,然后通过显式 using-声明 (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++98(段落的修订,该段落说:

每个 C 标头(每个标头都有一个表单 name.h 的名称(的行为就好像由相应的 cname 标头放置在标准库命名空间中的每个名称也放置在命名空间std的命名空间范围内,后跟显式 using 声明 (7.3.3(

这介于难以理解和不可能之间,因为它与大多数系统上现有的真实 C 标头冲突。因此,在 C++11 中,文本更改为您引用的文本。它允许以相反的方式实现它,就像他们在实践中一直做的那样 - 使用现有系统提供的 C 标头并将名称导入命名空间std

但是,还有一段说,无论实现以何种方式执行此操作,标头中的名称都必须具有相同的含义:

对于标准 C 库中T的每个类型,::Tstd::T 的类型保留给实现,并且在定义时,::T应与 std::T 相同。([外部类型],17.6.4.3.4(

是的,它们可以是不同的类型。使用C++类型;C 标头只是为了兼容性。

考虑一下,如果如上面答案的注释所暗示的那样,C++标头是按namespace std { #include "stdio.h" }实现的;那么::FILEstd::FILE将代表不同的类型。

相关文章: