对 abs(double) 的不明确重载调用
我有以下 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) ) {
...
}
并且 make
爆炸:
error: call of overloaded 'abs(double)' is ambiguous
也很有趣:
/usr/include/stdlib.h:785: note: candidates are: int abs(int)
如何指定编译器需要调用 cmath.h 中可以处理浮点数的 abs() ?
编译器信息(不确定这是否重要):
[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)
I have the following C++ code:
#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:
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?
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
标头
是 C std lib 标头。它在全局命名空间中定义了很多东西。标头
是该标头的 C++ 版本。它在命名空间 std 中定义了本质上相同的内容。 (存在一些差异,例如 C++ 版本带有某些函数的重载,但这并不重要。)标头
不存在。由于供应商不想维护本质上相同的标头的两个版本,因此他们想出了不同的可能性,只在幕后保留其中一个版本。通常,这是 C 标头(因为 C++ 编译器能够解析它,而相反的则无法解析),而 C++ 标头仅包含该标头并将所有内容放入命名空间
std
中。或者有一些宏魔法可以解析相同的标头,无论是否包含namespace std
。除此之外,在某些环境中,如果标头没有文件扩展名(例如编辑器无法突出显示代码等)会很尴尬。因此,一些供应商会将
设为单行代码,其中包含一些带有.h
扩展名的其他标头。或者有些人会将所有包含匹配的
映射到
(通过宏魔法,当__cplusplus 已定义,否则将成为 C 标头)或
或其他内容。这就是为什么在某些平台上,包括像
这样不应该存在的东西,最初会成功,尽管它可能会使编译器稍后严重失败。我不知道你使用哪个标准库实现。我想这是 GCC 附带的,但我不知道,所以我无法准确解释你的情况发生了什么。但它肯定是上述特定于供应商的黑客之一的组合,并且您包含了一个您不应该自己包含的标头。也许是
映射到
并带有您未定义的特定(一组)宏,所以你最终得到了这两个定义。但请注意,此代码仍然不应该编译:
全局命名空间中不应该有
abs()
(它是std::abs()
)。然而,根据上述实现技巧,很可能存在。稍后移植此类代码(或者只是尝试使用不允许这样做的供应商的下一个版本来编译它)可能会非常乏味,因此您应该密切关注这一点。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 namespacestd
. (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.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 withoutnamespace 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.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.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.Note, however, that this code still ought not to compile:
There shouldn't be an
abs()
in the global namespace (it'sstd::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 very tedious, so you should keep an eye on this.归结起来就是:
math.h
来自C
,创建于 10 多年前。在 math.h 中,由于其原始性质,abs()
函数“本质上”仅适用于整数类型,如果您想获取双精度数的绝对值,则必须使用fabs()
。当 C++ 创建时,它采用了 math.h 并使其成为 cmath。
cmath
本质上是 math.h,但针对 C++ 进行了改进。它改进了必须区分 fabs() 和 abs 之类的事情,并且只是为双精度和整数类型创建了abs()
。总之:
使用 math.h 并使用
abs()
表示整数,使用fabs()
表示双精度数或者
使用 cmath,只要有腹肌就可以解决所有问题(更简单且推荐)
希望这可以帮助任何遇到同样问题的人!
Its boils down to this:
math.h
is fromC
and was created over 10 years ago. In math.h, due to its primitive nature, theabs()
function is "essentially" just for integer types and if you wanted to get the absolute value of a double, you had to usefabs()
.When C++ was created it took
math.h
and made itcmath
.cmath
is essentially math.h but improved for C++. It improved things like having to distinguish betweenfabs()
and abs, and just madeabs()
for both doubles and integer types.In summary either:
Use math.h and use
abs()
for integers,fabs()
for doublesor
use cmath and just have abs for everything (easier and recommended)
Hope this helps anyone who is having the same problem!
使用 fabs() 而不是 abs(),它是相同的,但用于浮点数而不是整数。
Use fabs() instead of abs(), it's the same but for floats instead of integers.
就我而言,我在使用
labs()
而不是abs()
时解决了问题。In my cases, I solved the problem when using the
labs()
instead ofabs()
.