如何修复“错误:调用 'abs' 不明确”

AkT*_*hao 6 c++ cmath

我正在从 HackerRank 运行一个关于指针的简单 C++ 程序,它在网站上运行良好。但是,当我在 MacOS 上运行它时,我得到了error: call to 'abs' is ambiguous并且我不确定到底什么是模棱两可的。

我查看了类似问题的其他答案,但错误消息往往是Ambiguous overload call to abs(double),这不是我遇到的问题,因为我没有使用任何双打。我也试过包括头文件cmathmath.h,但问题仍然存在。

#include <stdio.h>
#include <cmath>

void update(int *a,int *b) {
    int num1 = *a;
    int num2 = *b;
    *a = num1 + num2;
    *b = abs(num1 - num2);
}

int main() {
    int a, b;
    int *pa = &a, *pb = &b;

    scanf("%d %d", &a, &b);
    update(pa, pb);
    printf("%d\n%d", a, b);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题出现在第 8 行。

zne*_*eak 10

完整的错误信息是:

$ clang++ test.cpp
test.cpp:8:10: error: call to 'abs' is ambiguous
    *b = abs(num1 - num2);
         ^~~
.../include/c++/v1/math.h:769:1: note: candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(double __lcpp_x) _NOEXCEPT {return ::fabs(__lcpp_x);}
^
.../include/c++/v1/math.h:769:1: note: candidate function
abs(long double __lcpp_x) _NOEXCEPT {return ::fabsl(__lcpp_x);}
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

abs您所拥有的三个重载<cmath>abs(float),abs(double)abs(long double); 这是模棱两可的,因为您有一个int参数,而编译器不知道要转换为哪种浮点类型。

abs(int)在 中定义<cstdlib>,因此#include <cstdlib>将解决您的问题。

如果您使用的是 Xcode,则可以在问题导航器 (?5) 中获取有关错误的更多详细信息,然后单击问题旁边的三角形。

  • 我现在有了一个稍微好一点的答案:“std::abs”仅在 C++17 中引入。在此之前,您必须使用“std::fabs”来获取浮点绝对值,并且您的同一程序会抱怨“abs”不存在(可能更好地突出显示您错过了正确的“#”)包括`)。 (2认同)
  • “abs”和“fabs”是重载函数,它们在给定不同参数类型的情况下执行不同的操作。`fabs` 对所有浮点类型进行重载,而 `abs` (在 C++17 中,或作为 C++ 早期版本中的扩展)对所有数字类型(整数和浮点)进行重载。调用“abs(double)”应该与调用“fabs(double)”相同。 (2认同)

ana*_*ana 8

对我来说,#include <cstdlib>没有解决问题,也许是因为我不需要包含任何要使用的东西abs。因此,如果它通过显式转换对其他人有帮助,那么它对我来说效果很好,如下代码所示:

*b = abs(int(num1 - num2));
Run Code Online (Sandbox Code Playgroud)


emm*_*lau 6

在模板化代码中,可能很容易忽略std::abs没有为无符号类型定义的内容。例如,如果为无符号类型实例化以下方法,编译器可能会正确地抱怨未定义std::abs

template<typename T>
bool areClose(const T& left, const T& right) {
    // This is bad because for unsigned T, std::abs is undefined
    // and for integral T, we compare with a float instead of
    // comparing for equality:
    return (std::abs(left - right) < 1e-7);
}

int main() {
    uint32_t vLeft = 17;
    uint32_t vRight = 18;
    std::cout << "Are the values close? " << areClose(vLeft, vRight) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

上面代码中的更好的定义areClose(),碰巧也解决了std::abs()未定义的问题,可能如下所示:

template<typename T>
bool areClose(const T& left, const T& right) {
    // This is better: compare all integral values for equality:
    if constexpr (std::is_integral<T>::value) {
        return (left == right);
    } else {
        return (std::abs(left - right) < 1e-7);
    }
}
Run Code Online (Sandbox Code Playgroud)