developer tip

abs (double)에 대한 모호한 오버로드 호출

optionbox 2020. 12. 30. 08:05
반응형

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)

컴파일러가 float를 처리 할 수있는 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)

헤더 <math.h>는 C std lib 헤더입니다. 글로벌 네임 스페이스에 많은 것을 정의합니다. 헤더 <cmath>는 해당 헤더 의 C ++ 버전입니다. 네임 스페이스에서 본질적으로 동일한 내용을 정의합니다 std. (C ++ 버전은 일부 함수의 오버로드와 함께 제공되는 것과 같은 몇 가지 차이점이 있지만 이는 중요하지 않습니다.) 헤더 <cmath.h>가 존재하지 않습니다.

공급 업체는 본질적으로 동일한 헤더의 두 가지 버전을 유지하기를 원하지 않기 때문에 그 중 하나만 배후에 두는 다른 가능성을 제시했습니다. 종종 그것은 C 헤더이고 (C ++ 컴파일러는 그것을 파싱 할 수 있지만 그 반대는 작동하지 않기 때문에) C ++ 헤더는 그것을 포함하고 모든 것을 namespace로 가져옵니다 std. 또는 동일한 헤더를 namespace std감싸 거나 감싸지 않고 구문 분석하는 매크로 마법이 있습니다. 여기에 일부 환경에서는 헤더에 파일 확장자가 없으면 어색합니다 (예 : 코드를 강조 표시하지 않는 편집기 등). 따라서 일부 공급 업체는 확장 <cmath>이있는 다른 헤더를 포함하여 한 줄로되어있을 것 .h입니다. 또는 일부는 모든 매칭을 포함하고지도 할 <cblah><blah.h>(매크로 마법을 통해 __cplusplus정의 되면 C ++ 헤더 가되고 그렇지 않으면 C 헤더가됩니다) <cblah.h>또는 무엇이든.

이것이 <cmath.h>존재해서는 안되는를 포함한 일부 플랫폼에서 처음에는 성공할 수있는 이유입니다. 비록 나중에 컴파일러가 눈에 띄게 실패하게 만들 수도 있습니다.

어떤 std lib 구현을 사용하는지 모르겠습니다. 나는 그것이 GCC와 함께 제공되는 것이라고 생각하지만 이것은 나는 모른다. 그래서 나는 당신의 사건에서 일어난 일을 정확히 설명 할 수 없습니다. 그러나 그것은 확실히 위의 공급 업체별 해킹 중 하나와 자신을 포함해서는 안되는 헤더를 포함하는 것의 혼합입니다. 아마도 정의하지 않은 특정 (세트) 매크로 <cmath>매핑되는 <cmath.h>경우 일 수 있으므로 두 정의를 모두 사용하게됩니다.

그러나이 코드는 여전히 컴파일되지 않아야합니다.

#include <cmath>

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

abs()전역 네임 스페이스 에는이 없어야 합니다 ( std::abs()). 그러나 위에서 설명한 구현 트릭에 따라 그럴 수도 있습니다. 이러한 코드를 나중에 포팅 (또는이를 허용하지 않는 공급 업체의 다음 버전으로 컴파일하려고 시도하는 것)은 매우 지루할 수 있으므로주의 해야합니다.


그것이 귀결 : math.h출신 C10 년 전에 만들어졌다. math.h에서 원시적 특성으로 인해 abs()함수는 정수 유형에만 "본질적으로"있으며 double의 절대 값을 얻으려면를 사용해야 fabs()합니다. C ++을 만들 때 그것은했다 math.h그것을했다 cmath. cmath본질적으로 math.h이지만 C ++에서는 개선되었습니다. fabs()그리고 abs 를 구별해야하는 것과 같은 것들을 개선 했고, 단지 abs()double 형과 integer 형 모두를 위해 만들어졌습니다 . 요약하면 : math.h를 사용 abs()하고 정수에 사용 , fabs()double에 사용하거나 cmath를 사용하고 모든 것에 abs 만 사용하십시오 (더 쉽고 권장 됨).

이것이 같은 문제가있는 모든 사람에게 도움이되기를 바랍니다!


abs () 대신 fabs ()를 사용하십시오. 동일하지만 정수 대신 부동 소수점의 경우입니다.


제 경우에는 labs()대신을 사용할 때 문제를 해결했습니다 abs().

참조 URL : https://stackoverflow.com/questions/1374037/ambiguous-overload-call-to-absdouble

반응형