苹果Clang和numeric_limits<unsigned __int128>::max()等于0?

4

我正在尝试找到解决一个明显的错误的最佳方法,其中numeric_limits<T>::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__ >= 16的测试来自于GCC邮件列表上的讨论,链接为128位整数——荒谬的文档?。结果是:
$ c++ -Wall test.cxx -o test.exe
$ ./test.exe
__int128 is available
numeric_limits<unsigned __int128>::max() is 0

苹果公司也已经放弃了该平台和工具,所以报告缺陷将无法解决问题。

我们该如何解决这个问题?


我不确定该如何继续操作。要修复代码中的问题,而不是上面的最小示例,我们真正地需要覆盖std命名空间中的函数。但是不允许覆盖std中的函数

以下是一个实际代码中出现问题的示例:

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

然而,切换到非苹果的测试机器会产生预期的结果:

$ 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

1
尝试使用更新的clang。我无法在Apple LLVM version 8.0.0 (clang-800.0.42.1)中重现此问题。我猜测在您较旧版本的clang中,std::is_arithmetic<__int128>::valuefalse,因此您会得到__libcpp_numeric_limits的默认实现,该实现对于min/max/等产生零。此外,如果t2为负(且类型为有符号数),则您的溢出检测是未定义行为。 - Cornstalks
2
在使用 numeric_limits 之前,您应该检查 is_specialized... - Marc Glisse
@Cornstalks - 谢谢。在OS X 10.9上,使用Xcode 6.0的Apple Clang版本已经固定。据我所知,没有其他版本(我们也不依赖用户安装或从头构建它们)。Add示例旨在演示完全特化的问题,而不是一个强大的加法。 - jww
@Cronstalk - 为什么苹果的Clang编译器没有抛出“未实现”或类似的错误?默默地产生错误结果有什么好处吗? - jww
1个回答

2

编写 notstd::numeric_limits<T>:std::numeric_limits<T>

为存在缺陷的 T 进行特化,重载 static max()(以及其他内容),使其具有正确的行为。

Add 中使用 notstd::numeric_limits

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


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