Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

namespace issues in c++11?

Tags:

c++

gcc

c++11

glibc

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?

like image 668
Tomasz Grobelny Avatar asked Oct 23 '12 22:10

Tomasz Grobelny


People also ask

What is a namespace problem?

Avoiding Name Collisions NET Framework namespaces address a problem sometimes called namespace pollution, in which the developer of a class library is hampered by the use of similar names in another library. These conflicts with existing components are sometimes called name collisions.

Why there is no namespace in C?

An unnecessary distinctive syntax: All other languages with namespaces just use '. ' as separator as its not ambiguous with other uses of '. '. And, more critically, c++ never introduced a scoped using directive.

Is using namespace std good or bad?

The statement using namespace std is generally considered bad practice. The alternative to this statement is to specify the namespace to which the identifier belongs using the scope operator(::) each time we declare a type.

What is the purpose of namespace in C?

Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.


2 Answers

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

like image 194
Xeo Avatar answered Oct 20 '22 14:10

Xeo


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…

like image 31
Cheers and hth. - Alf Avatar answered Oct 20 '22 14:10

Cheers and hth. - Alf