【问题标题】:Ambiguous call to abs对 abs 的模糊调用
【发布时间】:2015-07-17 01:15:51
【问题描述】:

我有一个自定义数据类型,实际上可以是floatdouble。在除 OSX 之外的所有操作系统上,我都能成功构建这个 C++11 模板:

#include <cmath>
#include <cstdlib>
#include <cstdint>

template< class REAL_T >
inline REAL_T inhouse_abs(REAL_T i_val)
{
    return std::abs((REAL_T)i_val);
}

int main()
{
    int32_t ui = 2;
    inhouse_abs(ui);
    return 0;
}

但是,clang 6.0 (3.5 LLVM) 报告了一个模棱两可的函数调用。如果我将abs 更改为fabs,则该错误在 OSX 上得到解决,但现在我的 Linux clang、gcc 和 Visual Studio 上出现了相同的错误。

带有晶圆厂的 Visual Studio 出错:

349 error C2668: 'fabs' : ambiguous call to overloaded function

更新

这个示例在我们的 OS X 系统上编译,尽管在几乎相同的项目中它没有。解决方案是在源代码中显式包含&lt;cstdlib&gt;,而不是在另一个标题中包含。原因尚不清楚,但似乎是 xcode/clang 未正确遵循我们的标头包含。

【问题讨论】:

  • 你有实际的错误文本吗?
  • @Collin 添加了 Visual Studio 错误。需要一分钟才能找到 clang 模拟。
  • @ShafikYaghmour 在该行生成错误,无需任何调用。
  • 那么你包括什么标题等等......
  • 已更新示例。

标签: c++ macos c++11 cmath


【解决方案1】:

问题在于libc++ 并不完全符合 C++11 的整体重载 std::abs in cmath

double      fabs( Integral arg ); (7)   (since C++11)

包含 cstdlib 可以解决您的问题,因为该标头具有专门针对整数类型的重载。

参考草案 C++11 标准部分 26.8 [c.math] 段落 11 说:

此外,应有足够的额外重载以确保:

并包括以下项目:

  1. 否则,如果对应于 double 参数的任何参数的类型为 double 或整数类型,则所有对应于 double 参数被有效地转换为 double。

由于LWG active issue 2192: Validity and return type of std::abs(0u) is unclear,这种情况很可能会改变。我猜libc++ 选择不在cmath 中提供重载,因为这个缺陷报告中提出了问题。

更多详情请参阅Is std::abs(0u) ill-formed?

【讨论】:

    【解决方案2】:

    解决方案是在 OS X 机器上显式地 #include &lt;cstdlib&gt;,因为某种原因 Visual Studio 在我们的依赖项中找到它并包含它,但 clang 没有。我将尝试重现我们项目具有的类似包含链,并以极简方式重现错误,因为它可能仍然是 Xcode 或 Visual Studio 的问题。

    【讨论】:

    • 帮助我完成了用 Xcode 编写的项目。谢谢!
    • 很高兴我为别人节省了一些时间!
    【解决方案3】:

    如果你有很多模板函数导致这个问题,你可以使用下面的插件替换:

    #include <cmath>
    #include <cstdlib>
    #include <type_traits>
    
    namespace util {
    
    
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_unsigned<T>::value,
                                          T> { return value; }
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_floating_point<T>::value,
                                          T> { return std::fabs(value); }
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_same<T, int>::value,
                                          T> { return std::abs(value); }
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_same<T, long>::value,
                                          T> { return std::labs(value); }
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_same<T, long long>::value,
                                          T> { return std::llabs(value); }
    template <class T>
    auto abs(T value) -> std::enable_if_t<std::is_signed<T>::value &&
                                              !std::is_floating_point<T>::value &&
                                              !std::is_same<T, int>::value &&
                                              !std::is_same<T, long>::value &&
                                              !std::is_same<T, long long>::value,
                                          T> { return std::abs(value); }
    
    
    } // namespace util
    

    只需将std::abs 调用替换为util::abs。 (需要c++11。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多