Why Are Some Functions in <Cmath> Not in the Std 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).

Why does cmath expose entities outside the std namespace?

Why does <cmath> expose entities outside the std namespace?

Because of history.

<cmath> header is a header inherited from the C standard library (where it is named <math.h>). In the C language, there is only the global namespace1 where all names are declared.

Since many C++ implementations are also C implementations, they often implement the inherited C standard header by including it as-is2 which means that it declares global names.

While there may be techniques to avoid (except in case of standard macros) declaring global names, it is unlikely that implementations that have been doing it since before standardisation would change the behaviour because that would break backward compatibility.

Is my standard library broken?

No. C++ standard allows this; All C standard library names are reserved for this (or any) use by the language implementation. You may not define them yourself.

Can I do something to avoid this?

You generally cannot prevent a standard library doing this.

You can technically avoid most of it by choosing to use a freestanding language implementation. But you'll lose nearly the entire standard library if you choose that.

You can minimise chances of name clashes by avoiding declaration of any global names yourself, except for a single namespace with sufficiently unique name. Something like:

namespace usr_bitmask::log {

}

1 Note that the concept of "name space" in the C language is something else.

2 And additionally, re-declares the names in the std namespace when using the <c... named header, as well as adds C++ specific overloads in some cases.

Why when I include cmath I need to use the namespace std too?

In C++ functions can be declared inside namespaces. Namespaces are just what its name infer, a collection of names.

To access a name (let's say the function pow()) that is declared inside the namespace std, you can access it in 2 ways: using the namespace access prefix std:: (i.e. std::pow()), or you can declare using namespace std. However as @Yksisarvinen mentioned, you should avoid the use of using namespace.

Why should we use std name space before functions of algorithm header and should not use it before functions of cmath header?

<cmath> is essentially a wrapper around math.c from the C standard library.

This header was originally in the C standard library as <math.h>. (source: https://en.cppreference.com/w/cpp/header/cmath)

C++ is a (almost) a superset of C, meaning that a C++ compiler should compile almost any program written in C. For this reason functions from the C standard library do not belong to the std namespace, which is a C++'s concept. Other examples: printf, fopen. Of course you can freely mix C++ standard library with C standard library functions, constants, macros etc.

For incompatibilities between C and C++ see for example Where is C not a subset of C++?

C++11 cmath functions not in std namespace for android NDK w/gcc-4.8 or clang 3.4

This seems to be a known issue with C++11 support on android. There is a known issue that indicates that a lot of the routines are missing:

When compiling c++ code with -std=c++11 and using gnustl_shared, many C99 math functions are not provided by the <cmath> header as they should.

You're probably better off assuming that only a limited subset of the c++ library is available for android - this seems to be indicated in the CPLUSPLUS-SUPPORT.html file in the docs/ for the ndk.

Mind you when I have:

APP_STL := c++_static

in my Application.mk and

LOCAL_CPPFLAGS  := -std=c++11

in my Android.mk, then files making use of std::cbrt and std::round compile cleanly; but it is against the static LLVM libc++, rather than against the gnu standard library.

Why did most implementations still have cmath functions in global namespace in C++03?

As stated in corresponding issue discussion in gcc bugzilla this approach will not allow including C header after C++ because of include guards:

#include <cmath>
#include <math.h> // include skipped by include guards

...
sin(x); // error: no sin in global namespace

As you mentioned standard requirements to C library wrappers were changed after issue was posted in defect report and previous requirements have been declared impractical from implementation point of view.

acosl is not in the std namespace?

This seems to be a libstdc++ bug.

cmath in libstdc++ doesn't just wrap an #include <math.h> in namespace std: it defines new functions that delegate to built-ins. I guess a definition wants adding to this source code. It was probably just an oversight when C++11 (via C99) introduced the function. (Though notice that the acos(long double __x) overload delegates to __builtin_acosl!)

In Clang, switching to libc++ resolves the issue. With libstdc++, using the global namespace version of acosl should also work.

You should raise a bug. I think it's covered by bug #79700.

C++ Cosine works without the std namespace - Why?

Unfortunately, library implementations are allowed to dump names from the C library into the global namespace as well as std, and many do. Even worse, in some cases only some overloads are available in the global namespace, leading to unexpected loss of precision if you don't specify the std version.

You should always use the std versions, but sadly there's no reliable way to enforce that, so you'll just have to tread carefully through this particular minefield.

Differentiating between functions with same name from different header files

There Are Two Approaches:

  1. Using ::round() instead of math::round(). This Approach is however compiler dependent and as cited here works well only for Microsoft Or GNU Compiler.
  2. Using cmath library. Supports the same functions as math.h but its functions are present in std namespace allowing you to use std::round() as cited here


Related Topics



Leave a reply



Submit