C++ 对 abs(double) 的模糊重载调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1374037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ambiguous overload call to abs(double)
提问by
I have the following C++ code:
我有以下 C++ 代码:
#include <math.h>
#include <cmath.h> // per http://www.cplusplus.com/reference/clibrary/cmath/abs/
// snip ...
if ( (loan_balance < 0) && (abs(loan_balance) > loan_payment) ) {
...
}
and make
blows up on:
并make
爆发:
error: call of overloaded 'abs(double)' is ambiguous
also of interest:
也有兴趣:
/usr/include/stdlib.h:785: note: candidates are: int abs(int)
How can I specify that the compiler needs to call the abs() in cmath.h that can handle floats?
如何指定编译器需要调用可以处理浮点数的 cmath.h 中的 abs() ?
Compiler info (Not sure if this matters):
编译器信息(不确定这是否重要):
[some_man@some_box ~/some_code]# gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr /share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)
回答by sbi
The header <math.h>
is a C std lib header. It defines a lot of stuff in the global namespace. The header <cmath>
is the C++ version of that header. It defines essentially the same stuff in namespace std
. (There are some differences, like that the C++ version comes with overloads of some functions, but that doesn't matter.) The header <cmath.h>
doesn't exist.
标头<math.h>
是 C std lib 标头。它在全局命名空间中定义了很多东西。标头<cmath>
是该标头的 C++ 版本。它在 namespace 中定义了本质上相同的东西std
。(有一些差异,比如 C++ 版本带有一些函数的重载,但这并不重要。)头文件<cmath.h>
不存在。
Since vendors don't want to maintain two versions of what is essentially the same header, they came up with different possibilities to have only one of them behind the scenes. Often, that's the C header (since a C++ compiler is able to parse that, while the opposite won't work), and the C++ header just includes that and pulls everything into namespace std
. Or there's some macro magic for parsing the same header with or without namespace std
wrapped around it or not. To this add that in some environments it's awkward if headers don't have a file extension (like editors failing to highlight the code etc.). So some vendors would have <cmath>
be a one-liner including some other header with a .h
extension. Or some would map all includes matching <cblah>
to <blah.h>
(which, through macro magic, becomes the C++ header when __cplusplus
is defined, and otherwise becomes the C header) or <cblah.h>
or whatever.
由于供应商不想维护本质上相同的标头的两个版本,因此他们想出了不同的可能性,只在幕后使用其中一个。通常,那是 C 头文件(因为 C++ 编译器能够解析它,而相反的则不起作用),而 C++ 头文件只包含它并将所有内容拉入 namespace std
。或者有一些宏魔法可以解析相同的标头,无论是否namespace std
包裹它。除此之外,在某些环境中,如果标题没有文件扩展名(例如编辑器未能突出显示代码等),则会很尴尬。因此,一些供应商可能<cmath>
是单行的,包括一些其他带有.h
扩展名的标头。或者有些人会将所有包含匹配映射<cblah>
到<blah.h>
(通过宏魔法,在__cplusplus
定义时成为 C++ 头文件,否则成为 C 头文件)<cblah.h>
或其他什么。
That's the reason why on some platforms including things like <cmath.h>
, which ought not to exist, will initially succeed, although it might make the compiler fail spectacularly later on.
这就是为什么在某些平台上,包括诸如<cmath.h>
,本不应该存在的东西,最初会成功的原因,尽管它可能会使编译器稍后严重失败。
I have no idea which std lib implementation you use. I suppose it's the one that comes with GCC, but this I don't know, so I cannot explain exactly what happened in your case. But it's certainly a mix of one of the above vendor-specific hacks and you including a header you ought not to have included yourself. Maybe it's the one where <cmath>
maps to <cmath.h>
with a specific (set of) macro(s) which you hadn't defined, so that you ended up with both definitions.
我不知道您使用的是哪个 std lib 实现。我想它是 GCC 附带的,但我不知道,所以我无法确切解释您的情况。但它肯定是上述特定于供应商的黑客之一的混合体,并且您包含了一个您不应该包含自己的标题。也许它是<cmath>
映射到<cmath.h>
您尚未定义的特定(一组)宏的那个,因此您最终得到了两个定义。
Note, however, that this code still ought not to compile:
但是请注意,这段代码仍然不应该编译:
#include <cmath>
double f(double d)
{
return abs(d);
}
There shouldn't be an abs()
in the global namespace (it's std::abs()
). However, as per the above described implementation tricks, there might well be. Porting such code later (or just trying to compile it with your vendor's next version which doesn't allow this) can be verytedious, so you should keep an eye on this.
abs()
全局命名空间中不应该有 an (它是std::abs()
)。但是,根据上述实现技巧,很可能存在。稍后移植此类代码(或者只是尝试使用不允许这样做的供应商的下一个版本来编译它)可能非常乏味,因此您应该密切注意这一点。
回答by Ruairi Hourihane
Its boils down to this: math.h
is from C
and was created over 10 years ago. In math.h, due to its primitive nature, the abs()
function is "essentially" just for integer types and if you wanted to get the absolute value of a double, you had to use fabs()
.
When C++ was created it took math.h
and made it cmath
. cmath
is essentially math.h but improved for C++. It improved things like having to distinguish between fabs()
and abs, and just made abs()
for both doubles and integer types.
In summary either:
Use math.h and use abs()
for integers, fabs()
for doubles
or
use cmath and just have abs for everything (easier and recommended)
它归结为:math.h
来自C
并创建于 10 多年前。在 math.h 中,由于其原始性质,该abs()
函数“本质上”仅适用于整数类型,如果您想获得双精度值的绝对值,则必须使用fabs()
. 当 C++ 被创建时,它采用math.h
并制作了它cmath
。cmath
本质上是 math.h,但针对 C++ 进行了改进。它改进了诸如必须区分fabs()
abs 和 abs 之类的事情,并且只abs()
针对双精度和整数类型。总而言之:使用 math.h 并abs()
用于整数、fabs()
双精度数或使用 cmath 并且对所有内容都使用 abs(更容易和推荐)
Hope this helps anyone who is having the same problem!
希望这可以帮助任何遇到同样问题的人!
回答by Nianliang
Use fabs() instead of abs(), it's the same but for floats instead of integers.
使用 fabs() 而不是 abs(),它是相同的,但对于浮点数而不是整数。
回答by Hai-Yang Li
In my cases, I solved the problem when using the labs()
instead of abs()
.
在我的情况下,我在使用labs()
代替abs()
.