Home > database >  Why does including <map> cause the div function to be defined in the global namespace?
Why does including <map> cause the div function to be defined in the global namespace?

Time:07-13

Consider the following code block:

void foo(){
  int a = div(1,2);
}

This normally will not compile, as the div function has not been declared. However, if I preceed the code with #include <map>, the code compiles. Why is map pulling in identifiers into the global namespace, and why the div function in particular? Is there a way to avoid this?

[mcve]

#include <map>

void foo(){
  int a = div(1,2);
}

int main()
{
  foo();    
}

live link - https://godbolt.org/z/Ye8rv4MTc

clang - <source>:4:7: error: no viable conversion from 'div_t' to 'int'

gcc - <source>:4:11: error: 'div' was not declared in this scope

MSVC - <source>(4): error C2440: 'initializing': cannot convert from 'div_t' to 'int'

CodePudding user response:

Any C standard library header is allowed to include any other C standard library header.

One of these headers is <cstdlib>, which is the C version of the <stdlib.h> C standard library header, which declares the function div_t div(int, int).

The C versions of the C standard library headers generally declare all entities in the std namespace. However the standard gives implementations permission to let them declare the entities in the global namespace first and then import them into the std namespace via using declarations.

Therefore, if you include any C standard library header at all you must expect that any entity from the C standard library may be declared in the global namespace. div_t div(int, int) is one of these.

All of this is however unspecified behavior. There is no guarantee that div_t div(int, int) will be declared (in either the global namespace or std) if you only include <map>.

If the name conflicts with some entity you want to declare yourself, the solution is to put all of your own stuff (except main) into your own namespace. This way name lookup will prefer your declaration inside the namespace to the one outside of it in the global namespace. This should anyways always be done. There are many potential pitfalls in the global namespace in particular as there are many additional reserved identifiers, names, signatures and so on in it.

CodePudding user response:

Not an answer, but include information for msvc, so it seems it is indeed being pulled in into the global namesapce

1>main.cpp
1>Note: including file: ...\VC\Tools\MSVC\14.32.31326\include\map
1>Note: including file:  ...\VC\Tools\MSVC\14.32.31326\include\tuple
1>Note: including file:   ...\VC\Tools\MSVC\14.32.31326\include\compare
1>Note: including file:    ...\VC\Tools\MSVC\14.32.31326\include\bit
1>Note: including file:      ...\VC\Tools\MSVC\14.32.31326\include\xstddef
1>Note: including file:       ...\VC\Tools\MSVC\14.32.31326\include\cstdlib
1>Note: including file:        C:\Program Files (x86)\Windows Kits\10\Include\10.0.20348.0\ucrt\stdlib.h
  • Related