Is it ok to qualify C functions with the `std` namespace? [duplicate] - c++

This question already has answers here:
When using C headers in C++, should we use functions from std:: or the global namespace?
(8 answers)
Closed 6 years ago.
When I use functions inherited from C, like the ones in <cmath> or <cstdlib>, should I qualify them as being part of the standard namespace std::log, or should I remain in the C-scope and use them as global functions? What about size_t?

If you use e.g. <math.h>
No, you shouldn't.
It is unspecified whether they are available in the namespace std on any particular implementation:
[C++11: D.5/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).
However, you should not be using this header:
[C++11: C.3.1/1]: For compatibility with the Standard C library, the C++ standard library provides the 18 C headers (D.5), but their use is deprecated in C++.
If you use e.g. <cmath>
Yes, you should.
It is unspecified whether they are available in the global namespace on any particular implementation:
[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).

Related

int abs(int) vs double abs(double) [duplicate]

This question already has answers here:
Ambiguous overload call to abs(double)
(4 answers)
Closed 12 months ago.
I'd like to understand the behavior of the following code, from the C++ Standard point of view (GCC 9.3, C++20):
#include <cstdlib>
template<class> struct type_tester;
int main() {
type_tester<decltype(abs(0.1))>{}; // int abs(int) overload is selected for some reason!
type_tester<decltype(std::abs(0.1))> {}; // double abs(double) overload is selected, as one would expect
}
So, int abs(int) is imported to the global namespace, while double abs(double) is not!
Why?
cstdlib is the C++ version of the C header stdlib.h. Such headers must introduce the names in the std namespace and they are allowed to introcude them in the global namespace. There is no double abs(double) in the C header, hence there is no reason to introduce it in the global namespace like it is done for the C variants of the funciton. Note that C has no namespaces, and having the function in the global namespace helps for compatibility with C code. For double abs(double) this is not an issue, because the function does not exist in the C header.
From cppreference:
For some of the C standard library headers of the form xxx.h, the C++
standard library both includes an identically-named header and another
header of the form cxxx (all meaningful cxxx headers are listed
above). The intended use of headers of form xxx.h is for
interoperability only. It is possible that C++ source files need to
include one of these headers in order to be valid ISO C. Source files
that are not intended to also be valid ISO C should not use any of the
C headers.
With the exception of complex.h , each xxx.h header included in the
C++ standard library places in the global namespace each name that the
corresponding cxxx header would have placed in the std namespace.
These headers are allowed to also declare the same names in the std
namespace, and the corresponding cxxx headers are allowed to also
declare the same names in the global namespace: including <cstdlib>
definitely provides std::malloc and may also provide ::malloc.
Including <stdlib.h> definitely provides ::malloc and may also provide
std::malloc. This applies even to functions and function overloads
that are not part of C standard library.
This applies even to functions and function overloads that are not part of C standard library. That means: It would be allowed to have double abs(double) in the global namespace too, but it is not required.
So, int abs(int) is imported to the global namespace,
Why?
Because the C++ standard allows it to be imported into the global namespace.
While double abs(double) is not!
Why?
Because the C++ standard doesn't require it to be imported into the global namespace.
Relevant standard quotes:
[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]).
Evidently, the C++ standard library implementation that you use had chosen to use the strategy described in the last paragraph of the quoted rule for the C standard library function, while having chosen not to use that strategy for the C++ standard library overloads. This specific outcome isn't guaranteed by the standard but it is conforming.
Another possible outcome would be that abs(0.1) would fail as use of an undeclared identifier. You cannot rely on C++ standard library names to be declared in the global namespace (unless you use the deprecated <name.h> C standard headers).

Is using namespace std; mandatory

How come this piece of code doesn't need std namespace.
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
Because you included a C header, not a C++ header.
[library.c/1]: The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety.
[depr.c.headers.other/1]: Every C header other than <complex.h>, <iso646.h>, <stdalign.h>, <stdbool.h>, and <tgmath.h>, 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, except for the functions described in [sf.cmath], the declaration of std::byte ([cstddef.syn]), and the functions and function templates described in [support.types.byteops]. [..] It is unspecified whether these names are first declared or defined within namespace scope ([basic.scope.namespace]) of the namespace std and are then injected into the global namespace scope by explicit using-declarations ([namespace.udecl]).
The last bolded part above says that you may have been able to use std::printf as well, but that there is no guarantee of that.
Also note that the header is deprecated:
[diff.mods.to.headers/1]: For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in [depr.c.headers], but their use is deprecated in C++.
On the flip side of the coin, if you'd included cstdio instead, you'd be guaranteed to get std::printf but the availability of ::printf (the fully-qualified name of the global symbol you used) would not be guaranteed:
[headers/4]: 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 [language.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]).
Short version:
C headers like stdio.h are in the global namespace, and possibly also in std;
C++ headers like cstdio are in the namespace std, and possibly also in the global namespace.
You only need using namespace std or std:: when you're using the namespace std,
The stdio.h header file allows you to use additional methods in the standard library that do not exist in all C++ code by default. By adding the line #include , you are instructing the compiler to copy the declarations in that header file into your code so you have access to them.
The line using namespace std allows you to utilize methods in the standard namespace without having to call out the standard name space each time. This helps eliminate typos, but could introduce other errors (if two namespaces have the same method signature).
For example,
#include <iostream>
std::cout << "Hello World!" << std::endl;
Could be written as:
#include <iostream>
using namespace std;
cout << "Hello World!" << endl;
using namespace std makes names from the standard namespace visible in your namespace.
stdio.h i a header that doesn't use its own namespace but instead puts its functions (e.g. printf) etc. in the namespace in which you include it (in your case the global namespace). Therefore you can access them directly.
Note that including headers in a namespace is not generally recommended (see first comment for an example), I only mentioned it for the sake of completeness since it might not be obvious for a beginner that the placement of the include makes a difference.

Why isn't "using std::xxx" needed for <cmath> functions?

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

Legacy standard C library headers and overloaded C++ functions

C++ language standard says in D.5
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 seems to state rather explicitly ("... each name ...", "...the same declarations...") that the old-style <name.h> headers must provide the same set of declarations as the new-style <cname> headers, but in global namespace. No exception is made for C++-specific overloaded versions of various C functions, for one example.
That appears to mean that <math.h> must provide three versions of sin function: sin(float), sin(double) and sin(long double) in global namespace. This, in turn, means that the following C++ code should fail overload resolution
#include <math.h>
int main() {
sin(1);
}
It does fail under MSVC++ compiler, but it compiles successfully under GCC and Clang. So, does GCC just ignore the standard requirement with regard to deprecated old-style headers? Or do I somehow misinterpret the wording in the standard?
Thanks to #hvd's comments I have seen the light, it turns out MSVC is correct and GCC should be complaining about the ambiguity as well.
The only differences between including <cmath> vs <math.h> are where the names are originally scoped, which is in namespace std for the former, and the global namespace for the latter (implementations are free to provide the names in the other namespace as well, but this isn't mandated), and the fact that including the .h variants of C headers is deprecated.

cmath header confusion

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.