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 headername.h
[...] as if by inclusion. In the C++ standard library, however, the declarations [...] are within namespace scope (3.3.6) of the namespacestd
. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespacestd
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.
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;
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
andstd::T
are reserved to the implementation and, when defined,::T
shall be identical tostd::T
. ([extern.types], 17.6.4.3.4)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With