#include <cmath> vs #include <math.h> in a C++ program [duplicate] - c++

This question already has answers here:
Should I include stddef.h or cstddef for size_t
(5 answers)
Should I include <xxxx.h> or <cxxxx> in C++ programs?
(2 answers)
Closed 9 years ago.
What are the considerations for including the former rather than the latter in a C++ program? I always include math.h, stdlib.h and never cmath, cstdlib etc. I don't understand the reason the latter even exist, could someone please enlighten me?

Prefer to include the <c ...> headers. They are C++ standard library headers. The <... .h> headers are headers defined by the C standard library:
The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety.
The C++ headers, for the most part, have content identical to the corresponding C library headers except that the names are all defined in the std namespace.
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

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

why getenv() can get name resolved without a std::? [duplicate]

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.

Use types in <cstdint> with or without namespace

In C++11 I can choose whether I want to use the types defined in with or without the namespace std::
At least my compiler (g++ 4.7) accepts both variants.
My question is: What is the recommended way to use the typedefs from cstdint. With or without the namespace? What are the advantages or disadvantages? Or is it only a matter of style?
so variant a):
#include <cstdint>
std::uint8_t n = 21;
resp:
#include <cstdint>
using std::uint8_t;
uint8_t n = 21;
or variant b):
#include <cstdint>
uint8_t n = 21;
Prefer names declared in the std namespace. The reason is given in §17.6.1.3/4 (ISO/IEC 14882:2011(E), C++11):
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).
If you use the names from the <cname> headers without std, your program is relying on unspecified requirements.
This was different in C++03 and earlier where names were only supposed to appear in the std namespace. However, the reality was that many implementations were simply injecting the contents of the C standard library headers <name.h> into std and so this was accommodated for in C++11. The corresponding section (§17.4.1.2/4) from the C++03 standard says:
Except as noted in clauses 18 through 27, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity, (Clause 7), as appropriate, as if by inclusion. In the C++ Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std.
Further to this, qualifying names with std:: helps to avoid collisions - you know exactly what you're getting if you fully qualify it. If you're really going to do using namespace std or using std::something, at least do it in as minimal a scope as you can.
In C++11, for the C headers that are explicitly named in the C++ standard, the following holds:
An implementation is required for the <foo.h> versions to add them in the global namespace, and allowed to add them to the std:: namespace.
An implementation is required for the <cfoo> versions to add them in the std:: namespace, and allowed to add them to the global namespace.
The reason for wrapping things in the std namespace in the <cstdint> header is to avoid name collisions, which are quite unpleasant when they happen. However, in this case, it is very unlikely that the types will be found somewhere else. So I would use <stdint.h>, especially because this feature was introduced in C before it was added to C++, and hence the <stdint.h> header is older than <cstdint>, and therefore available in older compilers.
If you have decided that you want these names in the global namespace, you should also prefer <stdint.h> to <cstdint> followed by using namespace std, as the latter will dump all the other std stuff from other <cfoo> headers yhou have included into the global namspace too, which you probably do not want, as many other standard names are much more collision-prone than the likes of uint8_t.
Include <cstdint> and use std:: or include <stdint.h> to use unqualified type names. There are some platforms (e.g. QNX SDP 6.6) on which <cstdint> doesn't declare those types in the global namespace.
My personal style is to always fully qualify names so it is clear where they come from. That is, I would use std::uint8_t. That is, I would include <cstdint> and use qualified names.
That said, note that use of std::uint8_t is only indicated if you really mean to use a type with exactly 8 bits. If the platform you are running your code on doesn't have such a type, e.g., because it uses 9 bit units as its basic entity, the program is supposed not to compile. If you want to use the smallest unsigned with 8 bits available, you want to use uint_least8_t.

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

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

Why do some includes need the .h and others not? [duplicate]

This question already has answers here:
Difference between using #include<filename> and #include<filename.h> in C++
(5 answers)
Closed 3 years ago.
Why is map imported as #include <map>, but stdio imported as #include <stdio.h>?
All standard C++ headers don't want the .h in the end. I read somewhere that the concept is that they don't need to be actual files, even if I never saw an implementation do it in another manner edit: actually the compiler intrinsics should work considering the headers included but not actually including them as files; see #Yttrill's comment.
For the stdio.h thing, in a C++ application you shouldn't include <stdio.h>, but you should instead include <cstdio>. In general, you shouldn't include the "normal" C headers, but their C++-ized counterparts, which haven't got the .h in the end, have a c in front and put all the symbols defined in them in the std namespace. So, <math.h> becomes <cmath>, <stdlib.h> becomes <cstdlib>, and so on.
In general, you should use the C++-ized versions of C headers both to avoid to pollute the global namespace (assuming you're not one of those guys who put using namespace std; everywhere) and to benefit of some C++ improvements to the standard C headers (e.g. added overloading to some math functions).
In general, the implementation of this whole thing is simply done by having such files without extension in the directory in which the compiler looks for the header files. In my g++ 4.4 installation, for example, you have:
matteo#teoubuntu:/usr/include/c++/4.4$ ls
algorithm cstdarg functional sstream
array cstdatomic initializer_list stack
backward cstdbool iomanip stdatomic.h
bits cstddef ios stdexcept
bitset cstdint iosfwd streambuf
c++0x_warning.h cstdio iostream string
cassert cstdlib istream system_error
ccomplex cstring iterator tgmath.h
cctype ctgmath limits thread
cerrno ctime list tr1
cfenv cwchar locale tr1_impl
cfloat cwctype map tuple
chrono cxxabi-forced.h memory typeinfo
cinttypes cxxabi.h mutex type_traits
ciso646 debug new unordered_map
climits deque numeric unordered_set
clocale exception ostream utility
cmath exception_defines.h parallel valarray
complex exception_ptr.h queue vector
complex.h ext random x86_64-linux-gnu
condition_variable fenv.h ratio
csetjmp forward_list regex
csignal fstream set
The C++-ized C headers in theory could just be a
namespace std
{
#include <original_C_header.h>
};
but in general they are more complicated to deal with implementation-specific problems (especially regarding macros) and to add C++-related functionality (see e.g. the previous example of added overloads in <cmath>).
By the way, the C++ standard (§D.5) do not say that the <c***> headers should behave as if they included the <***.h> headers in a namespace std directive, but the opposite:
For compatibility with the Standard C library, the C++ Standard library provides the 18 C headers [...]
Each C header, whose name has 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 name-space std and is followed by an explicit using-declaration (7.3.3)
Notice that such headers are considered deprecated (§C.2.1), so this is the main reason you shouldn't use them:
C.2.1 Modifications to headers
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++.
It's simply the name of the actual file on disk. There is (probably) no file called map.h or stdio in your standard include directory.
The C++ standard library moved away from the previous style of using .h toward not having .h at the end of the file names. This may possibly have been related to making the syntax look more like templates:
#include<vector>
vector<int> v;
(Preemptive comment: Yes, I know the above needs std:: to build, but it's just an illustration.)
It's just the way it's defined by the C++ Standard -- as it happens, map and stdio.h don't even have to be real files.
As a side-note, stdio.h is the header that was originally imported into C++ from the C standard libraries -- the C++ version is cstdio. In practical terms, this generally means that when you include cstdio instead, you get the stuff from stdio.h, but it's in namespace std.
Just to clarify: the stdio.h you include in C++ is the C++ version of what was originally a C header. But the C++ way of writing the include is cstdio.