如何修复“error: call to 'abs' is ambiguous”错误

17

我正在HackerRank上运行一个关于指针的简单C++程序,它在网站上正常运行。但是当我在MacOS上运行它时,出现了一个error: call to 'abs' is ambiguous错误,我不确定到底有什么不明确之处。

我已经查看了其他类似问题的答案,但错误消息通常是Ambiguous overload call to abs(double),这不是我的问题,因为我没有使用任何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;
}

我的问题出现在第8行。


4
使用 std::abs 就不会有问题。 - NathanOliver
1
自从 C++17std::abs 已在 <cmath> 中定义。来源 - Fureeish
2
当我使用std::abs时,我得到了相同的错误,但是当我使用#include <cstdlib>时,错误消失了,代码可以正常工作。 - AkThao
我想我找到了版本。它是G++ 4.2.1。 - AkThao
1
@Eljay 嗯,你不应该在C++中使用.h C头文件。 - eesiraed
显示剩余9条评论
6个回答

15

完整的错误消息是:

$ 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.

你从<cmath>库中拥有的abs函数有abs(float)abs(double)abs(long double)三个重载版本;因为你使用了一个int参数,编译器无法确定要转换成哪种浮点类型,所以存在二义性。

abs(int)<cstdlib>库中定义,因此使用#include <cstdlib>可以解决你的问题。

如果你正在使用Xcode,可以在Issues导航器(⌘5)中获取关于错误的更多详细信息,点击问题旁边的三角形。


1
那是否意味着 <cmath> 中没有定义 abs(int) 函数?如果是这样,为什么呢? - AkThao
@AkThao,原因可能是历史遗留问题,因为C最初没有浮点类型。我猜测浮点支持曾经是可选的,他们开始将所有内容放在math.h中。我无法立即列出math.h中主要不使用浮点类型的函数,而且我只能列出一些在外部使用它们的函数。 - zneak
2
我现在有一个稍微更好的答案:std::abs只在C++17中引入。在此之前,您必须使用std::fabs来获取浮点绝对值,而您的同样程序将抱怨abs不存在(可能更好地突出显示您缺少正确的#include)。 - zneak
fabsabs(float)abs(double)以及abs(long double)是一样的吗?另外,由于使用std::abs并没有修复我的代码,这是否意味着我正在使用早于C++17的版本?稍微相关的问题是,如何检查我正在使用哪个版本的C++(在终端中键入“C++ --version”只会给出编译器信息)? - AkThao
2
absfabs是重载函数,根据不同的参数类型执行不同的操作。fabs适用于所有浮点类型,而abs(在C++17中或在以前版本的C++中作为扩展)适用于所有数字类型(整数和浮点)。调用abs(double)应该与调用fabs(double)相同。 - zneak
关于你正在使用的C++版本,我不知道是否有一种非常简单的方式来获得答案。__cplusplus常量会给出一个年份和月份,但是因为平台允许定义扩展,例如在自称为C++98的环境中,您可以发现具备C++17功能。您可以使用--std=[...]参数告诉Clang您想要的特定方言,其中典型值包括c++14c++17gnu++14gnu++17。(GNU版本包括GCC定义的扩展。) - zneak

8

对我来说,#include <cstdlib>并没有解决问题,可能是因为我不必包含任何内容就可以使用abs。 所以,如果能帮助其他人,使用显式转换,像下面的代码一样,它对我很有效:

*b = abs(int(num1 - num2));

1
这是唯一在我的 Mac 上有效的解决方案。 - chm

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;
}

在上述代码中,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);
    }
}

1
如果您使用C编译器,应包含以下内容:

#include <stdlib.h>

使用abs而不是std::。 如果您使用C++编译器,则应将abs更改为std :: abs。

希望能帮到您:)


1
我正在使用C++编译器,但是出于某种原因,使用std::abs似乎没有任何作用。只有当我使用#include <cstdlib>时才有效。 - AkThao
这很奇怪...我尝试了两个在线的C++编译器,只需使用std::abs就可以工作。请看:https://ideone.com/wls3Tphttps://onlinegdb.com/BJzbpcDZH - NewMe
可能是我使用的是旧版本的C++。在上面的答案评论中,zneak说std::abs只在C++17中引入,而在此之前必须使用std::fabs。这就是我所经历的,std::abs不起作用,但std::fabs可以。在终端中,我尝试使用-std=c++17指定方言,但它返回一个错误,说无效值'c++17' - AkThao
在新的C++ Windows桌面应用程序中使用VS2019默认设置。只有#include <cstdlib>#include <cmath>可以获得浮点的abs。stdlib.h似乎不想接受一个浮点参数。:( - Laurie Stearn

0
只需将 #include 放在 #include 上方即可,错误便会消失。

1
目前您的回答写得不够清楚。请编辑并添加更多细节来帮助其他人理解它如何回答问题。您可以在帮助中心找到有关编写良好答案的更多信息。 - Community

-3

我只使用了#include <bits/stdc++.h>这个头文件,我的代码就可以正常工作了。

#include <bits/stdc++.h>  
using namespace std;
class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        int n = nums.size();
        if(n == 0 || n == 1)
            return {};
        vector<int> ans;
        for(int i = 0; i < n; i++)
        {
            if(nums[abs(nums[i])-1] < 0)
                ans.push_back(abs(nums[i]));
            else
                nums[abs(nums[i])-1] = -1 * nums[abs(nums[i])-1];
        }
        return ans;
    }
};

1
https://dev59.com/R1wZ5IYBdhLWcg3wIdR7 - Passerby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接