Math Interface VS Cmath in C++

Math interface vs cMath in C++

In the C++ standard, the math library functions are defined in two headers:

<cmath>

contains them in the namespace std (e.g. std::sin), while

<math.h>

contains them in the global namespace (so just sin).

There are further differences between the two: while <math.h> contains all the C math functions with distinct names for distinct types, such as

double sin(double);
float sinf(float);
long double sinl(long double);

etc., <cmath> contains overloaded functions such as

namespace std {
double sin(double);
float sin(float);
long double sin(long double);
}

etc. (C++ libraries might additionally export sinf from <cmath>, but you can't rely on this in a portable program.)

Finally, the fabs, fabsf and fabsl functions from the C standard library have become overloads of std::abs in <cmath>.

Though both headers are in the standard, you should really prefer <cmath>, as <math.h> is only there for backward compatibility with pre-standard C++ and C.

There's no such thing as <cmath.h> in standard C++.

#include cmath vs #include math.h in a C++ program

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

cmath header confusion

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.

Why are some functions in cmath not in the std namespace?

Implementations of the C++ standard library are permitted to declare C library functions in the global namespace as well as in std. Some would call this a mistake, since (as you've found) the namespace pollution can cause conflicts with your own names. However, that's the way it is, so we must live with it. You'll just have to qualify your name as arithmetic::sin.

In the words of the standard (C++11 17.6.1.2/4):

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

Including standard header files. string.h or cstring? or both?

<cstring> is newer; <string.h> is really there for backwards compatibility (and for C, of course). The difference is that <cstring> puts the string functions in the std namespace, while <string.h> puts them in the global namespace.

In addition, <cstring> changes the types of certain functions to promote type-safety. E.g., the C declaration

char *strchr(char const *, int);

is replaced by the overloads (in the std namespace)

char       *strchr(char       *, int);
char const *strchr(char const *, int);

In the case of <cmath> there are further differences with <math.h> which make <cmath> more idiomatic and less C-like.

Prefer <cstring> for new code and use the std:: prefix on the functions.

Why do you have to link the math library in C?

The functions in stdlib.h and stdio.h have implementations in libc.so (or libc.a for static linking), which is linked into your executable by default (as if -lc were specified). GCC can be instructed to avoid this automatic link with the -nostdlib or -nodefaultlibs options.

The math functions in math.h have implementations in libm.so (or libm.a for static linking), and libm is not linked in by default. There are historical reasons for this libm/libc split, none of them very convincing.

Interestingly, the C++ runtime libstdc++ requires libm, so if you compile a C++ program with GCC (g++), you will automatically get libm linked in.

How come cmath does not use templates and/or overloads

I don't know about Boost, but all of the standard functions in
<cmath> have overloads for the three standard types, so you
have e.g.:

double cos(double);
float cos(float);
long double cos(long double);

in place of C's:

double cos(double);
float cosf(float);
long double cosl(long double);

I'm not quite sure why you want a function template instead of
overloads. For most mathematic functions, no generic
implementation is possible; a correct implementation will depend
on precision, rounding rules, etc. which are different for each
type. So the alternative would be a template function without
a generic implementation, and three specializations. And what
does that buy you over the "simpler" overloaded functions?

Removing math.h from a project VS 2015 / 2017

Any standard library header may include any other; in VC++ the include path ending at <cmath> is iostream->istream->ostream->ios->xlocnum.

However in general including math.h/cmath should not in itself be a problem so long as the replacements you define have identical signatures and that you do not indirectly or otherwise use any interfaces that you have not defined. That is to say, it is not math.h that you need to remove - that is useful in ensuring comparability between the standard and your implementation. Rather what you need to do is prevent the linker from linking the math library (while still presumably linking other parts of the C library.

Unfortunately, this is not possible in VC++ because unlike GCC where mlib and cstdlib are separate libraries, in VC++ the entire standard library is a single entity. Moreover the C++ standard library has dependencies on that library, so you would have to replace more than just the math functions in order to avoid linking the standard library at all.

It is possible to instruct VC++ to ignore default libraries as follows:

Sample Image

but the monolithic nature of the standard library means that it will not help you much, since there are numerous other dependencies on even the simplest empty main() code because all the C run-time environment (the kind of stuff that is in crt0.o in GCC) is included in the same library.

Your best approach is to continue with your functions in their own namespace - that is after al what namespaces are for. In you library header file you could include macro definitions to avoid linking standard math functions:

#define sin mymath::sin

But that is not entirely satisfactory - if your header is included before any standard header that includes math.h (directly to indirectly), it may fail to link or even compile in ways that may be hard to fathom.

Why doesn't the C++ standard library provide constexpr versions of the cmath functions?

It hasn't been standardized yet. An initial proposal was submitted just last week, but only covering utility and linear operations and not any transcendental functions. Math is hard and floating-point math is complicated. For example, implementations don't allow overflows to infinity in constexpr, but this isn't yet clearly standardized.

The compiler's constexpr interpreter would have to special-case the math library interface, since unlike the rest of the standard library, it can't see its implementation.

GCC does offer constant evaluation of math functions as a nonconforming extension.



Related Topics



Leave a reply



Submit