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

Is this code standard conforming?

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

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

Explanation: The standard says [headers]:

[...] the contents of each header cname shall be the same as that of the corresponding header name.h [...] as if by inclusion. In the C++ standard library, however, the declarations [...] are within namespace scope (3.3.6) of the namespace std . It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).

So in case they aren't injected by explicit using-declaration, may they be different type? I don't think the "as if by inclusion" phrase is conclusive since the other half of the text clearly contradicts this requirement, requiring the names are within the std namespace.


I don't believe that paragraph says that they have to be identical. It is just a revision of the original (C++98) paragraph which said:

Every C header, each of which has a name of the form name.h behaves as if each name placed in the Standard library namespace by the corresponding cname header is also placed within the namespace scope of namespace std and is followed by an explicit using-declaration (7.3.3)

This was between hard and impossible to follow, because it conflicted with the existing real C headers on most systems. So, in C++11 the text was changed to the one you quote. It allows implementations to it the other way round, like they in practice have done all along - use existing system provided C headers and import the names to namespace std .

However, there is another paragraph saying that whichever way the implementation does this, the names in the headers must mean the same thing:

For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T . ([extern.types], 17.6.4.3.4)


Yes, that's standard conforming: FILE* is declared in stdio.h , std::FILE* in cstdio , and the two are the same because of the paragraph you cited.

(The only thing that's unspecified is whether, if you only include <cstdio> , you also have the same FILE* in the global namespace or not.)


Update: I believe that the types are actually the same on the nose, and that each type is declared only once and then injected in to the other namespace via a using declaration. The only thing that's unspecified is which one comes first. The corresponding opposite standard quote is D.5(2):

Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

Basically, that means that two implementations are possible:

"C came first":

// foo.h

struct Gizmo { /* ... */ };

// cfoo

#include "foo.h"
namespace std { using ::Gizmo; }


"C++ with C-compatibility:

// cfoo

namespace std 
{
    struct Gizmo { /* ... */ };
}

// foo.h

#include <cfoo>
using std::Gizmo;

Yes, they can be different types. Use the C++ types; the C headers are only there for compatibility.

Consider if as the comment to the answer above suggests, the C++ header were implemented as namespace std { #include "stdio.h" } ; then ::FILE and std::FILE would represent different types.

链接地址: http://www.djcxy.com/p/29766.html

上一篇: 使用名称空间会导致名称隐藏吗?

下一篇: `cname`和`name.h`中的类型可以是不同的类型?