代码之家  ›  专栏  ›  技术社区  ›  sebrockm

GCC和Clang在C++17中不编译std::hash<std::nullptr\u t>

  •  22
  • sebrockm  · 技术社区  · 6 年前

    https://en.cppreference.com/w/cpp/utility/hash 它说自从C++17

    声明模板std::hash的每个标准库头 所有cv非限定算术类型(包括任何扩展整数

    因此,符合C++17标准的编译器应该编译以下小程序:

    #include <functional>
    int main()
    {
        std::hash<std::nullptr_t> h;
        return h(nullptr);
    }
    

    std::hash<std::nullptr_t> 已(隐式)删除。 看见 here here

    Visual Studio 我会编译它。显然它回来了 0 672807365 .

    我能自己专门做一下然后回来吗 0 如果将它与其他散列组合,其他值(例如某些素数)不是更好吗?


    使现代化

    . 事实上,它正在回归 (价值在 eax ). 回来

    1 回复  |  直到 6 年前
        1
  •  20
  •   YSC    4 年前

    这个程序正确吗?

    [unord.hash]/2

    哈希的每个专门化要么启用,要么禁用,如下所述。[…]声明模板哈希的每个标头都提供了 hash 对于 nullptr_­t

    自从 <functional> 搞砸 样板 1. std::hash<std::nullptr_t> . 您的示例程序应该被任何符合C++17标准的实现所接受


    为什么不是呢?

    由于C++17还很年轻,一些细微的特性可能在最近的编译器中仍然缺失或有缺陷。请放心,gcc和clang在开发过程中会接受您的MCVE/ experimental 分支机构。

    但是我们找不到一个接受它的GCC开发版本;这就是为什么 已由引发错误报告 Lightness Races in Orbit (见 std::hashstd::nullptr_t Jonathan Wakely (见 revision267845 returns zero ).


    我可以自己专门化它并像Visual Studio一样返回0吗?

    您将编写显示未定义行为的代码 2. 分离 翻译单位:

    #include <functional>
    #include <type_traits>
    static_assert(
        false == std::is_default_constructible_v<std::hash<std::nullptr_t>>,
        "Explanation"
    );
    

    这将警告您的同事,并要求他们手动删除您的 而不是给他们带来严重的编译错误。


    看见 [functional.syn] .

    only allowed 专攻 std 程序定义类型的类模板(其中 零位 不是)。您还可以打破“一个定义”规则。