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

时间:2012-05-05 21:21:31

标签: c++ standards-compliance language-lawyer standard-library

此代码标准是否符合

#include <stdio.h>
#include <cstdio>

int main() {
    FILE *f1 = 0;
    std::FILE *f2 = f1;
}

说明:标准说[header]:

  

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

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

3 个答案:

答案 0 :(得分:3)

是的,这符合标准:FILE*stdio.hstd::FILE* cstdio中宣布,由于您引用的段落,两者是相同的。

(唯一没有说明的是,如果你包括<cstdio>,你是否在全局命名空间中也有相同的FILE*。)


更新:我认为的类型实际上与鼻子相同,并且每个类型只声明一次,然后通过using声明注入另一个名称空间。唯一没有说明的是哪一个首先出现。相应的相反标准引用是D.5(2):

  

每个C头,每个头都有一个名称为name.h的行为,就好像每个由相应的cname头放在标准库命名空间中的名称放在全局命名空间范围内。未指定是否首先在名称空间std的名称空间作用域(3.3.6)中声明或定义这些名称,然后通过显式using-declarations(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;

答案 1 :(得分:2)

我不相信那段说它们必须是相同的。它只是对原始(C ++ 98)段落的修订,其中说:

  

每个C标头(每个标头都具有 name.h 形式的名称)就好像每个名称由相应的 cname 标头放置在标准库命名空间中一样也放在命名空间std的命名空间范围内,然后是显式 using-declaration (7.3.3)

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

但是,还有另一段说明无论执行方式如何,标题中的名称必须具有相同的含义:

  

对于标准C库中的每个类型T,类型::Tstd::T都保留给实现,并且在定义时,::T应与{相同} {1}}。 ([extern.types],17.6.4.3.4)

答案 2 :(得分:1)

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

考虑一下,如上面答案的评论所示,C ++标题是作为namespace std { #include "stdio.h" }实现的;然后::FILEstd::FILE代表不同的类型。