9

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?

Tomasz Grobelny
  • 2,666
  • 3
  • 33
  • 43
  • 3
    I have found that compilers frequently violate the rule that everything the `c*` correspondents of the C standard library headers define has to be in the `std` namespace. Apparently `string` includes `cstdlib` which violates the rule and puts `div` in the global namespace. I would call it a compiler defect. – Seth Carnegie Oct 23 '12 at 22:13
  • The interesting thing is that it works correctly until I specify the c++11 mode. And whether it is a compiler bug I am not 100% sure: clang does the exact same thing... – Tomasz Grobelny Oct 23 '12 at 22:20
  • 3
    @SethCarnegie - the reason that library implementations frequently violate that rule is that there is no such rule. There was, in C++03, but it was wishful thinking; it couldn't be done, and the rule was dropped with C++11. – Pete Becker Oct 23 '12 at 22:20
  • Is there any standard way to prevent this conflict without having to qualify my div variable on every use? – Tomasz Grobelny Oct 23 '12 at 22:25
  • @PeteBecker That's disappointing. I knew C++11 allowed it but I had wanted implementations to not do it. I never realized C++03 actually didn't allow the c headers to pollute the global namespace and that implementations simply weren't in compliance. – bames53 Oct 23 '12 at 22:25
  • @PeteBecker ah thank you for that info, I had no idea. – Seth Carnegie Oct 23 '12 at 22:25
  • @bames53 - not so much **simply** weren't in compliance, but **couldn't** comply on some systems. If you don't control the C headers you really can't avoid putting the names that they define into the global namespace. – Pete Becker Oct 23 '12 at 22:30
  • @PeteBecker: Surely every C++ compiler is in control of its C headers? – GManNickG Oct 24 '12 at 01:54
  • @GManNickG - no, sometimes they're developed by different groups. Seems to me this was an issue at Sun. – Pete Becker Oct 24 '12 at 13:03

3 Answers3

4

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 header cname shall be the same as that of the corresponding header name.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 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).”

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…

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
4

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

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.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 1
    Well, not useless; the guarantee that you get is that `#include ` puts a bunch of names into the global namespace, and that `#include ` puts a bunch of names into namespace `std`. – Pete Becker Oct 23 '12 at 22:31
  • 1
    Another good reason to use the cheaders is to avoid macros. For example, `` generally undefs all the macros from `` ([reference](http://msdn.microsoft.com/en-us/library/f9xkk9fk.aspx)). – Jesse Good Oct 23 '12 at 23:31
  • @JesseGood: do you know whether Visual C++ (your reference) is standard-conforming in this respect? – Cheers and hth. - Alf Dec 13 '12 at 20:28
  • @Cheersandhth.-Alf: AFAIK, it is standard conforming. libstdc++ does the same thing. The C standard says `Any function declared in a header may be additionally implemented as a function-like macro`. In C++, only `Names which are defined as macros in C shall be defined as macros in the C++ standard library`, since the C standard says `may be additionally implemented`, there is no restriction on making them macros in C++. – Jesse Good Dec 13 '12 at 21:36
2

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 std and 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.

bames53
  • 86,085
  • 15
  • 179
  • 244