Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

are C functions declared in <c____> headers guaranteed to be in the global namespace as well as std?

Tags:

c++

c

namespaces

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 would 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).

like image 421
Evan Teran Avatar asked Apr 06 '10 18:04

Evan Teran


2 Answers

Here's a nice synopsis of the situation (with some relaity 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>, and std::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 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.

like image 122
Michael Burr Avatar answered Sep 28 '22 01:09

Michael Burr


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 -- #includeing 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.

like image 34
Jerry Coffin Avatar answered Sep 28 '22 00:09

Jerry Coffin