【问题标题】:Apple Clang and numeric_limits<unsigned __int128>::max() is 0?Apple Clang 和 numeric_limits<unsigned __int128>::max() 为 0?
【发布时间】:2026-01-03 00:50:01
【问题描述】:

我正在尝试找出解决 numeric_limits&lt;T&gt;::max() 返回 0 而不是最大值的明显错误的最佳方法。

一、测试程序:

$ cat test.cxx
#include <iostream>
#include <limits>

int main(int argc, char* argv[])
{
#if (__SIZEOF_INT128__ >= 16)
    std::cout << "__int128 is available" << std::endl;
#else
    std::cout << "__int128 is not available" << std::endl;
#endif

    unsigned __int128 m = std::numeric_limits<unsigned __int128>::max();
    if (m == 0)
        std::cout << "numeric_limits<unsigned __int128>::max() is 0" << std::endl;
    else
        std::cout << "numeric_limits<unsigned __int128>::max() is not 0" << std::endl;

    return 0;
}

__SIZEOF_INT128__ &gt;= 16 测试来自128-bit integer - nonsensical documentation? 的 GCC 邮件列表上的讨论。

结果:

$ c++ -Wall test.cxx -o test.exe
$ ./test.exe
__int128 is available
numeric_limits<unsigned __int128>::max() is 0

Apple 也放弃了平台和工具,因此错误报告无法解决问题。

我们如何解决这个问题?


我不确定如何继续。为了解决代码中的问题,与上面的最小示例相反,我们真的需要覆盖std 命名空间中的函数。但是overriding a function in std is not allowed

这是一个示例,说明为什么它在实际代码中存在问题:

template<class T1, class T2>
T1 Add(const T1& t1, const T2& t2)
{
    if (std::numeric_limits<T1>::max() - t2 > t1)
        throw std::runtime_error("overflow");

    return t1 + t2;
}

在上面的代码中,我们必须为T1 = __int128T2 可以想象的每个组合提供完整的专业化。不现实。


问题机器上的编译器版本:

$ c++ --version
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

但是,跳转到非 Apple 测试机器会产生预期结果:

$ clang++-3.5 --version
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix

$ clang++-3.5 -Wall test.cxx -o test.exe

$ ./test.exe
__int128 is available
numeric_limits<unsigned __int128>::max() is not 0

【问题讨论】:

  • 尝试更新的clang。我无法用Apple LLVM version 8.0.0 (clang-800.0.42.1) 重现该问题。我的猜测是 std::is_arithmetic&lt;__int128&gt;::value 在旧版本的 clang 中是 false,因为这样你会得到 __libcpp_numeric_limits 的默认实现,这对于 min/max/等产生零。另外,如果t2 为负(并且类型已签名),我认为您的溢出检测是UB。
  • 你应该在使用numeric_limits之前检查is_specialized...
  • @Cornstalks - 谢谢。修复了带有 Xcode 6.0 的 OS X 10.9 上的 Apple Clang 版本。据我所知,没有其他版本(我们不依赖用户安装它们或从头开始构建它们)。 Add 示例旨在通过完全专业化来演示问题,而不是强大的添加。
  • @Cronstalk - 为什么 Apple 的 Clang 无法抛出 “未实现” 或类似内容?默默地产生不好的结果有什么好处?

标签: c++ clang numeric-limits


【解决方案1】:

notstd::numeric_limits&lt;T&gt;:std::numeric_limits&lt;T&gt;

专门针对有错误的T,以正确的行为重载static max()(以及其他任何东西)。

Add 中使用notstd::numeric_limits

或者使用更新的编译器和/或标准库。

【讨论】: