Ambiguous overload call to abs(double)

独自空忆成欢 提交于 2019-12-18 10:15:11

问题


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)

回答1:


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.




回答2:


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!




回答3:


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




回答4:


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



来源:https://stackoverflow.com/questions/1374037/ambiguous-overload-call-to-absdouble

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!