问题描述
我有以下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
吹起:
错误:调用重载的'abs(double)'是不明确的
/usr/include/stdlib.h:785:注意:候选项是:int abs(int)
我如何指定编译器需要调用cmath.h中可以处理浮点数的abs()?
编译器信息(不确定是否重要):
some_man @ some_box〜/ some_code]#gcc -v
使用内置规格。
目标:i386-redhat-linux
配置:../configure --prefix = / usr --mandir = / usr / share / man --infodir = / usr / share / 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 / 1.4.2-gcj-1.4.2.0 / jre --with-cpu = generic -host = i386-redhat-linux
线程模型:posix
gcc版本4.1.2 20080704(Red Hat 4.1。 2-44)
解决方案标题
< math.h>
是一个C std lib头文件。它在全局命名空间中定义了很多东西。标头< cmath>
是该标头的C ++版本。它在命名空间std
中定义了基本相同的东西。 (有一些差异,像C ++版本带有一些函数的重载,但这没关系。)头< cmath.h>
不存在。
由于供应商不想维护两个版本的本质上相同的标题,他们想出了不同的可能性,只有一个在幕后。通常,这是C头(因为C ++编译器能够解析,而相反的不工作),和C ++头只是包括它,并拉所有的命名空间
std
。或者有一些宏的魔法来解析相同的头,有或没有命名空间std
包裹。另外,在某些环境中,如果头文件没有文件扩展名(如编辑器无法突出显示代码等),这是很尴尬的。因此,一些供应商将具有< cmath>
是一行,包括一些具有.h
扩展的其他头。或者一些映射包括匹配< cblah>
到< blah.h>
,当__ cplusplus
被定义,否则变成C头部)或< cblah.h>
管他呢。
这就是为什么在一些平台上,包括
< cmath.h>
,将最初成功,虽然它可能使编译器失败在后来壮观。
我不知道你使用哪个std lib实现。我想这是一个与GCC,但我不知道,所以我不能解释发生在你的情况下发生了什么。但它肯定是一个混合的上述供应商特定的黑客,你包括一个标题,你不应该包括自己。也许这是
< cmath>
映射到< cmath.h>
宏,您没有定义,所以你结束了两个定义。
但请注意,此代码仍然不应编译:
#include< cmath>
double f(double d)
{
return abs(d);
}
不应有
abs / code>在全局命名空间(它是
std :: abs()
)。然而,根据上述实现方法,可能存在。稍后移植此类代码(或者只是尝试使用您的供应商的下一个版本编译它不允许这样做)可能会非常乏味,所以您应该密切注意这一点。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)
解决方案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:
#include <cmath> double f(double d) { return abs(d); }
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.这篇关于对abs(双)的模糊过载调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!