2009-09-03 4 views
47

私は、次のC++コードを持っている:あいまいなオーバーロードの呼び出し(ダブル)

関心のも
error: call of overloaded 'abs(double)' is ambiguous 

#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は上に吹く

/usr/include/stdlib.h:785: note: candidates are: int abs(int) 

コンパイラがfloatを処理できるcmath.hのabs()を呼び出す必要があることをどのように指定できますか?

コンパイラ情報(これが重要かどうかわからない):

[[email protected]_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) 
+6

あなたが引用しているcplusplusページには、cmath.hが含まれているとは言えません。それはcmathと言います。これはmath.hのC++バージョンです。両方を含めないでください。 –

答えて

42

ヘッダ<math.h>は、Cのstd libのヘッダです。これは、グローバル名前空間にたくさんのものを定義します。ヘッダ<cmath>は、そのヘッダのC++バージョンです。基本的に名前空間stdに同じものを定義します。 (いくつかの違いがありますが、C++バージョンにはいくつかの関数のオーバーロードがありますが、それは問題ではありません)。<cmath.h>というヘッダは存在しません。

ベンダーは本質的に同じヘッダーの2つのバージョンを維持したくないので、それらの中の1つだけをバックグラウンドで持つ可能性があります。それはしばしばCのヘッダです(C++コンパイラはそれを解析することができますが、逆は動作しません).C++ヘッダーはそれを含み、すべてを名前空間stdにプルします。または、namespace stdの有無にかかわらず同じヘッダーを解析するためのマクロマジックがあります。このため、いくつかの環境では、ヘッダーにファイル拡張子がないと(エディタがコードを強調表示しないなど)、それが面倒です。したがって、一部のベンダーは<cmath>を1つのライナーとし、他のヘッダーには.hの拡張子を付けることができます。または、マップする場合は、<cblah><blah.h>にマッチさせるか(__cplusplusが定義されている場合はマクロマジックを使用し、それ以外の場合はCヘッダーになります)、<cblah.h>などです。

<cmath.h>のようなものを含むいくつかのプラットフォームでは、存在しないはずのプラットフォームでは、後でコンパイラが驚異的に失敗する可能性があります。

どのstdlib実装を使用するのか分かりません。私はそれがGCCに付属しているものだと思いますが、これはわかりませんので、あなたのケースで何が起こったのか正確には説明できません。しかし、それは確かに上記のベンダー固有のハックと、あなた自身を含めてはいけないヘッダーを含んでいます。おそらく、<cmath><cmath.h>にマップされていて、定義されていない特定のマクロがあると、両方の定義になります。

注意は、しかし、このコードはコンパイルするべきではないということ:

#include <cmath> 

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

は、グローバルな名前空間(それはstd::abs()のだ)でabs()があるべきではありません。しかし、上に説明した実装のトリックによると、うまくいくかもしれません。このようなコードを後で移植することは、非常にになる可能性がありますので、これに注意する必要があります。

30

これまでのところ:math.hCであり、10年以上前に作成されました。 math.hでは、その基本的性質のために、abs()関数は整数型の "本質的"なので、double型の絶対値を取得したい場合は、fabs()を使用しなければなりません。 C++を作成したときにはmath.hとなり、cmathとなりました。 cmathは本質的にmath.hですが、C++では改善されています。 fabs()とabsを区別しなければならないようなものが改善され、倍精度と整数型の両方に対してabs()が作成されました。要約すると 次のいずれか 使用のmath.hとダブルス または 使用cmathための整数のabs()fabs()を使用し、ちょうどすべて(簡単かつ推奨)

希望のために腹筋を持っている、これは同じ問題を抱えている人を助けます!

11

abs()の代わりにfabs()を使用します。整数ではなく浮動小数点数でも同じです。

+6

これは 'std'名前空間では正確ではありません。' abs'は 'float'、' double'などのオーバーロードです。 – Flexo

+0

gcc6エラーが修正されました:オーバーロードされた 'abs(uint32_t)'の呼び出しはあいまいです –

+0

@Sérgio uint32_tは符号なしなので、absへの呼び出しを削除するだけです。 (代わりに、暗黙のうちにfabs(double)のためにuint32_tをdoubleにキャストしてから、結果を整数にキャストすると仮定します) – Raptor007

関連する問題