are C functions declared in <c____> headers guaranteed to be in the global namespace as well as std?
So this is something that I've always wondered but was never quite sure about. So it is strictly a matter of curiosity, not a real problem.
As far as I understand, whenyou do something like #include <cstdlib>
everything (except macros of course) are declared in the std::
namespace. Every implementation that I've ever seen does this by doing something like the following:
#include <stdlib.h>
namespace std {
using ::abort;
// etc....
}
Which of course has the effect of things being in both the global namespace and std
. Is this behavior guaranteed? Or is it possible that an implementation could put these things in std
but not in the global namespace? The only way I can think of to do that woul开发者_JAVA技巧d be to have your libstdc++ implement every c function itself placing them in std
directly instead of just including the existing libc headers (because there is no mechanism to remove something from a namespace). Which is of course a lot of effort with little to no benefit.
The essence of my question is, is the following program strictly conforming and guaranteed to work?
#include <cstdio>
int main() {
::printf("hello world\n");
}
EDIT: The closest I've found is this (17.4.1.2p4):
Except as noted in clauses 18 through 27, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity, (Clause 7), as appropriate, as if by inclusion. In the C + + Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std.
which to be honest I could interpret either way. "the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C" tells me that they may be required in the global namespace, but "In the C + + Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std." says they are in std (but doesn't specify any other scoped they are in).
Here's a nice synopsis of the situation (with some reality vs. what the standard says) from Stephan T. Lavavej of the MSVC team (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
>
also,<cstddef>
,<cstdlib>
, andstd::size_t
etc should be used!I used to be very careful about that. C++98 had a splendid dream wherein
<cfoo>
would declare everything within namespace std, and<foo.h>
would include<cfoo>
and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now
<cfoo>
is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace.<foo.h>
is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.In reality and in C++0x, including
<cfoo>
is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with<cfoo>
.This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .
(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)
I've never been fond of the <cfoo>
headers myself, and found that I've always use <foo.h>
. Now I feel like I can stop being anxious about my lack of C++ 'purity' in that regard.
At the present time, no. In fact, even though the code will work with every compiler I now of, it's really not supposed to work at all -- #include
ing one of the c* headers is only supposed to give you access to the names inside of namespace std.
Since implementation of this was such a pain (getting it right essentially required duplicating the entire C library as a C++ library in the right namespace), in C++ 0x they've changed the requirements a bit -- your code is now allowed to work, though (at least if memory serves) it's still not required to work.
I cannot speak for the standards, as I have not read them, but one could envision a C++ environment that is not built on top of a C environment, or where the C environment is a compatibility layer on top of underlying C++ APIs. In such a case, these guarantees may not be made. I would be surprised if such an implementation would be prohibited from being a compliant implementation.
精彩评论