问题
Can somebody please explain the following:
$ cat test.cpp
#include <string>
std::string div;
$ g++ -c test.cpp
$ g++ -std=c++11 -c test.cpp
test.cpp:2:13: error: 'std::string div' redeclared as different kind of symbol
In file included from /usr/include/c++/4.7.1/cstdlib:66:0,
from /usr/include/c++/4.7.1/ext/string_conversions.h:37,
from /usr/include/c++/4.7.1/bits/basic_string.h:2814,
from /usr/include/c++/4.7.1/string:54,
from test.cpp:1:
/usr/include/stdlib.h:787:14: error: previous declaration of 'div_t div(int, int)'
$
Shouldn't the div symbol be in std namespace also for C++11 mode? Or is it something specific to my system?
回答1:
/usr/include/stdlib.h
Every name in a .h C stdlib header resides in the global namespace (obviously).
Additionally, any cHEADER C++ stdlib header will define the corresponding names from HEADER.h in the std namespace, but is also allowed to have them in the global namespace (so they can just do
// cHEADER
#include <HEADER.h>
namespace std{
using ::one_name_from_HEADER;
using ::another_name_from_HEADER;
// and so on...
}
and be done with it).
§D.5 [depr.c.headers]
p2 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 correspondingcnameheader 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).p3 [ Example: The header
<cstdlib>assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header<stdlib.h>assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. —end example ]
As you can see, the same is also true the other way around (<HEADER.h> may introduces names to the std namespace, as if
// HEADER.h
#include <cHEADER>
using std::one_name_from_HEADER;
using std::another_name_from_HEADER;
// and so on...
}
), which makes the whole distinction between those headers rather... useless, really.
回答2:
div is a function from <stdlib.h>.
In C++11, the <cblah> headers were allowed to place stuff in the global namespace.
C++11 §17.6.1.2/4:
“Except as noted in Clauses 18 through 30 and Annex D, the contents of each headercnameshall be the same as that of the corresponding headername.h, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++standard library, however, the declarations (except for names which are defined as macros in C) 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 namespace std by explicit using-declarations (7.3.3).”
Reflecting the reality of common C++ implementations.
So nothing changed, really, except the formal: that the behavior you see is now sanctioned by the standard instead of being an implementation artifact that one had to make allowance for.
Also, the formal change makes it easier to argue on SO that one should better include .h headers rather than cxxx headers…
回答3:
17.6.4.3.3/1 states:
Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage,182 both in namespace
stdand in the global namespace.
div is a name declared as a function with external linkage in the header cstdlib, and therefore is a reserved name in the global namespace. You're not allowed to use this name.
来源:https://stackoverflow.com/questions/13040139/namespace-issues-in-c11