GCC和Clang不在C++ 17中编译std :: hash <std :: nullptr_t>

seb*_*ckm 22 c++ hash gcc clang c++17

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

声明模板std :: hash的每个标准库头为std :: nullptr_t和所有cv-unqualified算术类型(包括任何扩展整数类型),所有枚举类型和所有指针类型提供std :: hash的启用特化.

因此,符合C++ 17的编译器应该编译这个小程序:

#include <functional>
int main()
{
    std::hash<std::nullptr_t> h;
    return h(nullptr);
}
Run Code Online (Sandbox Code Playgroud)

但是,GCC和Clang都报告了一个错误,说默认构造函数std::hash<std::nullptr_t>是(隐式)删除的.请看这里这里自己验证.

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

Q1: GCC和Clang是否仍然缺少这个C++ 17功能,因为诚然这不是一个高优先级的功能?或者我错过了什么?

Q2:我可以自己专注并像Visual Studio一样返回吗?一些其他价值,例如某些素数,不会更好地将它与其他哈希相结合吗?0 672807365


更新

由于我有限的汇编程序知识,我认为Visual Studio正在返回0.实际上,它正在返回672807365(值为eax).所以,我的第二个问题基本上是自己回答:我不会回到0我的专业领域来解决这个问题.

YSC*_*YSC 18

这个程序是否正确?

cppreference.com是对的.从最新的C++标准草案:

[unord.hash]/2

散列的每个特化都可以启用或禁用,如下所述.[...]声明模板散列的每个标头提供hashfor nullptr_­t和所有cv非限定算术,枚举和指针类型的启用特化.

由于<functional>声明了hash模板1,它必须提供一个启用的特化std::hash<std::nullptr_t>.任何符合C++ 17的实现都应该接受您的示例程序.


为什么不呢?

C++ 17还很年轻,一些微妙的功能可能在最近的编译器中仍然缺失或有缺陷.请放心,您的MCVE在开发/ 实验分支中被gcc和clang接受.

我们找不到GCC的开发版本接受它; 这就是为什么OrbitLightness Races提出错误报告(参见std :: hash未实现)并由Jonathan Wakely修改(见revision267845)(并返回零).


如何在等待实施修复时修复程序?

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

您将编写将显示未定义行为2的代码.这样做需要您自担风险.记录得很好.例如,将以下内容放在一个单独的翻译单元中:

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

这将警告您的同事,并要求他们手动删除您的专业化,std::hash<std::nullptr_t>而不是让他们一个讨厌的编译错误.


1)[functional.syn].

2)只能std为程序定义的类型(nullptr_­t不是)专门化类模板.您也可以打破一个定义规则.