I compile my program in Linux - it has the following line:
std::sqrt((double)num);
On Windows, it is ok. However, on Linux, I get an error:
sqrt is not a member of std
I have already included math.h.
What is the problem with that?
Change the directive to #include <cmath>. C++ headers of the form <cxxxxxxx> are guaranteed to have the standard names in std namespace (and may optionaly provide them in global namespace). <xxxxxx.h> are not.
it is simply because <math.h> does not declare the functions in namespace std. It has been included into the C++ standard only for compatibility reasons. The correct C++ include would be <cmath>.
§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 of the namespace std and are then injected into the global namespace scope by explicit using-declarations.
That your code worked under windows was pure luck - if you want to call it so. The last sentence gives a hint what might happen under windows, but not under linux: under windows, obviously the names are valid in both the global namespace and namespace std.
Related
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.
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).
This question already has answers here:
why and how does rand() exist both in global and std namespace in cstdlib?
(2 answers)
Closed 7 years ago.
getenv() has a C++ implementation which can be included in the header file . So it is a member of namespace std. However, the getenv() function can be get resolved correctly in my code even without a std::getenv(), which means my follow program can be compiled and run without any error and warning. So why getenv() as a name member of namespace std can get resolved without std::? My OS and compiler is Ubuntu 12.04 i386 and g++ 4.8.1 respectively.
#include <cstdlib>
#include <iostream>
int main()
{
char * path_env;
path_env = getenv("PATH"); //without a name resolve operation std::getenv()
std::cout << path_env << std::endl;
return 0;
}
Try to use search before asking questions. This is duplicate of why and how does rand() exist both in global and std namespace in cstdlib?
C++11 Standard: D.5 C standard library headers
Para 3:
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.
When you include one of the c* headers, the standard requires that the names are in the std namespace, but allows them to be first placed into the global namespace and then copied over to std.
Conversely, when you include one of the *.h headers (which are deprecated), the standard requires that the names are placed into the global namespace, but allows them to be first declared in the std namespace and copied over.
From [headers] / 4
[...] 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).
From [depr.c.headers]
Technically for maximum portability you should prefix names (except macros of course) in the c* headers with std, although in my limited experience I haven't come across an implementation that doesn't declare them in the global namespace as well.
Your code is probably not portable. BTW, it seems to work even without including <cstdlib>. If we look carefully at the declaration:
http://en.cppreference.com/w/cpp/utility/program/getenv
we see that indeed it belongs to cstdlib, and the usual convention is that all headers that starts with c + previous C-like header are now in namespace std;, so you should be using std::.
Same happens with std::string, seems to be included by many standard library headers, although if you look at the standard, you shouldn't rely on this.
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.
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.