I had a quick question. Is there a way to force the standard namespace to have the std:: scope qualifier? Something like abs and what not; all std functions have to have their scope defined.
I'm not using namespace std anywhere nor am I using std::abs or something like that. It might be important to say I have Windows.h included, which I feel may be where some of these unscoped functions are originating from.
The standard does not forbid other namespaces to have functions that are named abs just because there are functions named abs in std namespace. That's true of all other functions defined in the std namespace.
If you want to be certain that you use std::abs. and not any other version of abs, then by all means, use std::abs. Then, it's immaterial whether there are other versions of abs defined in the windows.h header file.
Calling abs instead of std::abs you are simply using abs from C
The rule in C++ is that #include <cmath> puts the declaration of abs in the namespace std and is allowed to also put the declaration of abs in the global namespace.
Another rule in C++ is that #include <math.h> puts the declaration of abs int he global namespace and is allowed to also put the declaration of abs in the namespace std.
So, no, you can't assume that #include <cmath> won't put abs into the global namespace.
The reason for this rule instead of the "obvious" one that #include <cmath> puts names only in std is that the latter rule can be nasty to implement if the C++ implementors don't also have control over the C headers. In that case, the C++ headers would have to have duplicate declarations for all of the C functions, and any change to the C headers would have to be carried through into the C++ headers, which produces a logistical nightmare.
Related
#include <cmath>
int abs;
int main()
{
}
This code throws the compilation error
error: 'int abs' redeclared as different kind of symbol
note: previous declaration 'int abs(int)'
The same thing happens if I include it from cstdlib.
I read this documentation https://en.cppreference.com/w/cpp/numeric/math/abs
where it is nowhere mentioned that abs would be defined outside std. In fact, it explicity mentions it as std::abs everywhere.
The same thing happens with other functions, such as sqrt.
Why is this happening? How can I use these functions without cluttering my namespace? If not possible, are there c++ alternatives?
Why is abs not in std?
Your question is slightly wrong. abs is in std. Let me assume that you're asking "Why is abs also in the global namespace?".
The C++ standard allows the C standard functions to be declared in the global namespace in addition to being declared in the std namespace.
Why is this happening?
Because those functions are from the C standard library, and because standard allows it to happen, and because of the way your standard library was implemented.
How can I use these functions without cluttering my namespace?
Those names are reserved to the language implementation in the global namespace. There's no way to avoid it.
Don't treat the global namespace as "your namespace". The global namespace is cluttered, and it always will be. You need to work around that.
If not possible, are there c++ alternatives?
The C++ alternative is to declare your abs in your namespace:
namespace my_very_own_namespace {
int abs;
}
You should declare everything1 in your own namespace, except:
That namespace itself
main
Template specialisations of names in other namespaces where that is allowed
Cross-language API's i.e. anything extern "C"
The hardest part is figuring out a unique name for your own namespace, since it mustn't be one that is already used by the C standard library, nor preferably any name used by other libraries in the global namespace.
1 Following this rule of thumb is hardly necessary when writing tiny exercise programs etc. But it becomes essential when writing large programs and relying on third party libraries, not to mention when writing those libraries for others to use.
Standard quotes:
[extern.names]
Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage,171 or as a name of namespace scope in the global namespace.
[headers]
Except as noted in [library] through [thread] and [depr], the contents of each header cname is the same as that of the corresponding header name.h as specified in the C standard library.
In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope of the namespace std.
It is unspecified whether these names (including any overloads added in [support] through [thread] and [depr]) are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations ([namespace.udecl]).
For all of the other standard library headers you can include, it is necessary to specify the namespace through any of the following methods:
using namespace std;
using std::xxx;
int main() {
std::xxx;
}
The sole exception I've encountered so far is in the <cmath> library, when all of their functions I've used thus far do not need any of the above in order to use them without specifying the namespace. Why is that?
Note: I may be wrong that <cmath> is the only standard library header that doesn't need the namespace to be specified, or that every function in <cmath> behaves like this. I just haven't encountered exceptions to what I've said in daily use yet.
The C++ Standard allows implementations to place names declared in standard C headers in the global namespace.
From the C++ Standard (17.6.1.2 Headers)
...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).
I understand that rand(), as an example function from <cstdlib>, exists both in the global and the std namespace.
In effect the following will compile without errors, i.e. both calls to std::rand() and rand() will be legit.
#include <cstdlib>
int main() {
std::rand();
rand();
}
What is the use for this and how exactly is it implemented (the function being in both namespaces)?
The behavior is Uspecified behavior as per standard.
As per the standard including cstdlib imports the symbol names in std namespace and possibly in Global namespace. If you rely on symbol names being included in global namespace then your program is non portable and you are relying on behavior of a specific implementation.
To not rely on the implementatio behavior you must:
Include cstdlib and use fully qualified name for rand.
std::rand()
References:
C++11 Standard: D.5 C standard library headers
Para 3:
[ 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 ]
Good Read:
Should I include <xxxx.h> or <cxxxx> in C++ programs?
The reason is that it's originally a C function. It comes from C.
C++ re-implemented C functions like these into a std namespace. There is no difference that I know of, but it is recommended that C++ programmers use the function in the std:: namespace, first including the "c"whatever header (which is what you have indeed done with the "cstdlib" header).
(Plain C programmers would include the "stdlib.h" header, by the way.)
What is the namespace for math functions? Global or std?
Consider cos function. It has 3 overloads. But there is also legacy cos from math.h. C doesn't know anything about function overloading. Therefore cos(x) can't be resolved to cos(float). The solution is to call the single precision version explicitly cosf(x). Did I miss anything?
You get the same functions by including <math.c> and <cmath> in C++, the only differences is the namespace. I.E. including <math.h> also gives you the overload.
In theory, in C++03, using <math.h> gives you the symbols defined in the global namespace and also in the std namespace while using <cmath> gives you the symbols defined in the std namespace and not in the global namespace.
The practice is different and C++ 0X aligned the theory with the practice. <math.h> gives you the symbols defined in the global namespace and perhaps also in the std namespace while using <cmath> gives you the symbols defined in the std namespace and perhaps also in the global namespace.
They are in the std namespace. But, for backwards compatibility reasons the cmath header also shows them in the global namespace with a using std::cos;.
The cXXX headers place all their stuff in the std namespace. They may also put them in the global namespace but it's not required.
This is from C++0x, the upcoming standard, section D.7:
2/ 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).
3/ [ 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 ]
This is unchanged from section D.5 from C++03 (it's made more explicit in the newer standard but the effect is the same):
2/ 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 also placed within the namespace scope of the namespace std and is followed by an explicit using-declaration.
3/ [Example: The header <cstdlib> provides its declarations and definitions within the namespace std. The header <stdlib.h> makes these available also in the global namespace, much as in the C Standard. —end example]
If you include the 'old-style' XXX.h header, it's placed in both namespaces (in both iterations of the standard).
If you are using C++ you can rely on the function overloading.
There are three version of cos:
double cos ( double x );
float cos ( float x );
long double cos ( long double x );
But if you are using only C or you want portabilty only the double version of this function exists with this name. The float function is cosf.
Does the runtime library pollute the global namespace?
I don't think you really understand the terms you are using, but the names in the C++ Standard Library exist in the std namespace, so the answer is no. The names in the header files that originated in the C Standard Library are placed in the global namespace, if you #include them via the .h filenames, such as:
#include <stdio.h>
if you #include them like this:
#include <cstdio>
then the names exist in both global and std namespaces.
The reason for placing objects in the std namespace is not so much to avoid "namespace polution", which is hardly a value neutral term, but to avoid name clashes.
The runtime library is required to use reserved identifiers. Without namespace qualification, these must begin with two underscores: __start, etc.
You are not allowed to use reserved names. The library is not allowed to use your names. If either crosses over to the other, it is "pollution" which is illegal.
Essentially, the situation is the same for C and C++ except, as the other answers point out, in C++ most standard library names have namespace qualification.
Most of the library cleanly goes in namespace std: -- however, for backwards compatibility with C, you may choose to "pollute" the global namespace by including old headers like <math.h> (which puts lots of names in the global namespace) instead of the proper new ones like <cmath> (which uses the std: namespace properly).