Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么<;cmath>;不在std名称空间中?_C++_Namespaces_Cmath - Fatal编程技术网

C++ 为什么<;cmath>;不在std名称空间中?

C++ 为什么<;cmath>;不在std名称空间中?,c++,namespaces,cmath,C++,Namespaces,Cmath,我正在开发一个可以处理多种算术类型的项目。因此,我制作了一个标题,其中定义了用户定义的算术类型的最低要求: 用户定义的算法。h: typedef double ArithmeticF; // The user chooses what type he // wants to use to represent a real number namespace arithmetic // and defines th

我正在开发一个可以处理多种算术类型的项目。因此,我制作了一个标题,其中定义了用户定义的算术类型的最低要求:

用户定义的算法。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);
...
}
Prototype declarations for math functions; helper file for <math.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)
{
...
困扰我的是,当我使用这样的代码时:

#include "user_defined_arithmetic.h"

void some_function()
{
    using namespace arithmetic;
    ArithmeticF lala(3);
    sin(lala);
}
我得到一个编译器错误:

error: call of overloaded 'sin(ArithmeticF&)' is ambiguous
candidates are:
double sin(double)
const ArithmeticF arithmetic::sin(const ArithmeticF&)
我从未使用过
标题,只有
标题。我从未在头文件中使用过
using namespace std

我使用的是gcc 4.6.*。我检查了包含不明确声明的标题是什么,结果是:

mathcalls.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);
...
}
Prototype declarations for math functions; helper file for <math.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)
{
...
数学函数的原型声明;的帮助文件。 ... 我知道,
包括
,但它应该通过std名称空间屏蔽声明。我深入查看
标题,发现:

cmath.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);
...
}
Prototype declarations for math functions; helper file for <math.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)
{
...
。。。
#包括
...
//去掉那些代替实函数定义的宏。
#未定义abs
#未定义分区
#未定义acos
...
命名空间std\u GLIBCXX\u可见性(默认)
{
...

<> P> >命名空间STD在 <>代码>包含< /代码>之后,这里有什么错误吗?还是我误解了什么?

< P> C++标准库的实现允许在全局命名空间中声明C库函数,也可以在<代码> STD 中声明。(正如您所发现的)名称空间污染可能会导致与您自己的名称冲突。然而,这就是它的方式,因此我们必须接受它。您只需将您的名称限定为
算术::sin

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

< C++标准库中的p>但是,声明(除了 在C)中定义为宏的名称在名称空间
std
的名称空间范围(3.3.6)内 未指定这些名称是否首先在全局命名空间范围内声明,然后注入 通过显式使用声明(7.3.3)将其转换为命名空间std


如果您真的愿意,您可以随时围绕
cmath
编写一个小包装,内容如下:

//stdmath.cpp
#include <cmath>
namespace stdmath
{
    double sin(double x)
    {
        return std::sin(x);
    }
}

//stdmath.hpp
#ifndef STDMATH_HPP
#define STDMATH_HPP
namespace stdmath {
    double sin(double);
}
#endif

//uses_stdmath.cpp
#include <iostream>
#include "stdmath.hpp"

double sin(double x)
{
    return 1.0;
}

int main()
{
    std::cout << stdmath::sin(1) << std::endl;
    std::cout << sin(1) << std::endl;
}
//stdmath.cpp
#包括
命名空间stdmath
{
双正弦(双x)
{
返回std::sin(x);
}
}
//stdmath.hpp
#ifndef STDMATH_水电站
#定义STDMATH\U水电站
命名空间stdmath{
双重罪恶(双重);
}
#恩迪夫
//使用_stdmath.cpp
#包括
#包括“stdmath.hpp”
双正弦(双x)
{
返回1.0;
}
int main()
{

std::cout这只是开始解决这个问题的一次卑微尝试。(欢迎提出建议。)

我已经处理这个问题很长时间了。一个案例是问题非常明显的是:

#include<cmath>
#include<iostream>

namespace mylib{
    std::string exp(double x){return "mylib::exp";}
}

int main(){
    std::cout << std::exp(1.) << std::endl; // works
    std::cout << mylib::exp(1.) << std::endl; // works

    using namespace mylib;
    std::cout << exp(1.) << std::endl; //doesn't works!, "ambiguous" call
    return 0;
}
有了它,这就行了

using namespace mylib;
std::cout << exp(1.) << std::endl; //now works.
使用名称空间mylib;

std::cout一些您可能需要重新考虑的事情:当使用算术类型(整数类型+双精度+浮点)时,它通常更有效(并且更常见)按值传递而不是按引用传递。在调用需要特定版本的函数时,请限定调用,而不是使用命名空间X添加
。或者,您可以使用using指令(
使用算术::sin
)。最后,通过编辑
typedef
来更改类型的整个方法是一个非常糟糕的主意。@DavidRodriguez-dribeas:谢谢!请你提示我一个替代解决方案好吗?我使用的是通过引用传递,因为数字可以是自定义类型。这意味着它甚至可以有几千字节大。我希望在内联函数时DavidRodriguez dribeas,我知道C++的方法是声明一个抽象类,但是我使用矩阵计算的一个库在使用内置类型时使用了显著的优化。不想失去这一优势您的实现可以是一个只使用功能的模板(不管类与否是不同的问题,如果您要求,免费函数都可以)。您的算法将适用于任何算术类型,用户代码可以决定在本地使用何种类型,而无需修改
typedef
。也就是说,用户无需在标题中搜索
typedef
。此外,您还可以在单个应用程序中使用多种类型。此外从红帽博客中看到Jonathan Wakely的观点。Wakely是GNU的C++标准库之一,他专门讨论了数学函数及其可能造成的麻烦。总之,C++有过载,因此有三个代码<代码ABS>代码>三代码>日志<代码>等。BLE < /COD>和 long double < /代码>以满足您的需要。但是C只有每个函数中的一个。这不能完全解决问题,请考虑<代码>命名空间MyLIB {double Sin(double x){返回1;}}int(){使用名称空间mylib;std::cout@alfC no你不需要。这个答案的全部要点是在
stdmath
cpp
文件中包含
,而不是
hpp
头。
名称空间std
中的任何声明都是UB。更糟糕的是
std::exp
对float和double-an都有重载d积分,而
exp
仅用于双精度。因此
使用命名空间std;
声明可以更改结果!