对 abs(double) 的不明确重载调用

发布于 2024-08-03 17:22:14 字数 1220 浏览 5 评论 0原文

我有以下 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忆依然 2024-08-10 17:22:14

标头 是 C std lib 标头。它在全局命名空间中定义了很多东西。标头 是该标头的 C++ 版本。它在命名空间 std 中定义了本质上相同的内容。 (存在一些差异,例如 C++ 版本带有某些函数的重载,但这并不重要。)标头 不存在。

由于供应商不想维护本质上相同的标头的两个版本,因此他们想出了不同的可能性,只在幕后保留其中一个版本。通常,这是 C 标头(因为 C++ 编译器能够解析它,而相反的则无法解析),而 C++ 标头仅包含该标头并将所有内容放入命名空间 std 中。或者有一些宏魔法可以解析相同的标头,无论是否包含 namespace std 。除此之外,在某些环境中,如果标头没有文件扩展名(例如编辑器无法突出显示代码等)会很尴尬。因此,一些供应商会将 设为单行代码,其中包含一些带有 .h 扩展名的其他标头。或者有些人会将所有包含匹配的 映射到 (通过宏魔法,当 __cplusplus 已定义,否则将成为 C 标头)或 或其他内容。

这就是为什么在某些平台上,包括像 这样不应该存在的东西,最初会成功,尽管它可能会使编译器稍后严重失败。

我不知道你使用哪个标准库实现。我想这是 GCC 附带的,但我不知道,所以我无法准确解释你的情况发生了什么。但它肯定是上述特定于供应商的黑客之一的组合,并且您包含了一个您不应该自己包含的标头。也许是 映射到 并带有您未定义的特定(一组)宏,所以你最终得到了这两个定义。

但请注意,此代码仍然不应该编译:

#include <cmath>

double f(double d)
{
  return abs(d);
}

全局命名空间中不应该有 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 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.

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.

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:

#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 very tedious, so you should keep an eye on this.

夜夜流光相皎洁 2024-08-10 17:22:14

归结起来就是: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 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)

Hope this helps anyone who is having the same problem!

难理解 2024-08-10 17:22:14

使用 fabs() 而不是 abs(),它是相同的,但用于浮点数而不是整数。

Use fabs() instead of abs(), it's the same but for floats instead of integers.

不打扰别人 2024-08-10 17:22:14

就我而言,我在使用 labs() 而不是 abs() 时解决了问题。

In my cases, I solved the problem when using the labs() instead of abs().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文