为什么<cmath>中的某些函数不在std命名空间中?

Mar*_*dik 27 c++ namespaces cmath

我正在开发一个适用于多种算术类型的项目.所以我制作了一个标题,其中定义了用户定义的算术类型的最低要求:

user_defined_arithmetic.h:

typedef double ArithmeticF;   // The user chooses what type he 
                              // wants to use to represent a real number

namespace arithmetic          // and defines the functions related to that type
{

const ArithmeticF sin(const ArithmeticF& x);
const ArithmeticF cos(const ArithmeticF& x);
const ArithmeticF tan(const ArithmeticF& x);
...
}
Run Code Online (Sandbox Code Playgroud)

令我不安的是,当我使用这样的代码时:

#include "user_defined_arithmetic.h"

void some_function()
{
    using namespace arithmetic;
    ArithmeticF lala(3);
    sin(lala);
}
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误:

error: call of overloaded 'sin(ArithmeticF&)' is ambiguous
candidates are:
double sin(double)
const ArithmeticF arithmetic::sin(const ArithmeticF&)
Run Code Online (Sandbox Code Playgroud)

我从来没有使用过<math.h>标题,只有<cmath>.我从来没有using namespace std在头文件中使用过.

我正在使用gcc 4.6.*.我检查了含有模糊声明的标题是什么,结果证明是:

mathcalls.h:

Prototype declarations for math functions; helper file for <math.h>.
...
Run Code Online (Sandbox Code Playgroud)

我知道,这<cmath>包括<math.h>,但它应该屏蔽std命名空间的声明.我深入了解<cmath>标题并找到:

cmath.h:

...

#include <math.h>

...

// Get rid of those macros defined in <math.h> in lieu of real functions.
#undef abs
#undef div
#undef acos
...

namespace std _GLIBCXX_VISIBILITY(default)
{
...
Run Code Online (Sandbox Code Playgroud)

所以空间std开始#include <math.h>.这里有什么问题,还是我误解了什么?

Mik*_*our 22

允许C++标准库的实现在全局命名空间中声明C库函数std.有人会称这是一个错误,因为(正如你所发现的)命名空间污染可能会导致与你自己的名字发生冲突.但是,就是这样,所以我们必须忍受它.你只需要将你的名字限定为arithmetic::sin.

用标准的话来说(C++ 11 17.6.1.2/4):

但是,在C++标准库中,声明(在C中定义为宏的名称除外)在命名空间的命名空间范围(3.3.6)内std.未指定是否首先在全局命名空间范围内声明这些名称,然后通过显式using-declarations将其注入命名空间std(7.3.3).