【问题标题】:GCC and Clang don't compile std::hash<std::nullptr_t> in C++17GCC 和 Clang 不在 C++17 中编译 std::hash<std::nullptr_t>
【发布时间】:2019-06-06 10:03:23
【问题描述】:

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

声明模板 std::hash 的每个标准库头文件 为 std::nullptr_t 和 所有 cv 非限定算术类型(包括任何扩展整数 types)、所有枚举类型和所有指针类型。

所以,一个 C++17 兼容的编译器应该编译这个小程序:

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

但是,GCC 和 Clang 都报告了一个错误,指出 std::hash&lt;std::nullptr_t&gt; 的默认构造函数已(隐式)删除。 请参阅herehere 自行验证。

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

Q1: GCC 和 Clang 是否仍然缺少这个 C++17 特性,诚然这不是一个高优先级的特性?还是我错过了什么?

Q2:我是否可以像 Visual Studio 一样只专注于它并返回 0 672807365不会有其他值,例如一些素数,将其与其他哈希组合更好?


更新

由于我对汇编程序的了解有限,我认为 Visual Studio 正在返回 0。实际上,它正在返回672807365eax 中的值)。 所以,我的第二个问题基本上可以自己回答:我不会在我的专业领域返回0 来解决这个错误。

【问题讨论】:

  • 抱歉,回滚了我的编辑。错字在源...
  • @user463035818 cppreference 是一个维基。比回滚更好,您可以更正该页面。我刚刚做了,你可以回滚你的回滚。
  • @YSC 哈哈,我又检查了一遍,发现有一个大胖子Edit 按钮。我想我已经习惯了,以至于在某些时候我开始忽略它。下次我就知道了
  • 在 clang HEAD 上工作,返回 156。wandbox.org/permlink/tu1WxRoqhGwv6Cm7
  • libstdc++ 中的错误? libc++ 很好(使用 -stdlib=libc++)

标签: c++ gcc hash clang c++17


【解决方案1】:

这个程序正确吗?

cppreference.com 是对的。来自最新的 C++ 标准草案:

[unord.hash]/2

如下所述,哈希的每个特化要么被启用,要么被禁用。 [...] 每个声明模板哈希的标头都为 nullptr_­t 和所有 cv 非限定算术、枚举和指针类型提供启用的 hash 特化。

由于&lt;functional&gt; 声明了hash 模板1,它必须为std::hash&lt;std::nullptr_t&gt; 提供启用的特化。 任何符合 C++17 的实现都应接受您的示例程序


为什么不是呢?

C++17 还很年轻,一些微妙的特性可能在最近的编译器上仍然缺失或存在缺陷。请放心,您的 MCVE 已被 gcc 和 clang 在其 development/experimental 分支中接受。

我们找不到接受它的 GCC 的开发版本;这就是为什么Lightness Races in Orbit 提出了一个错误报告(请参阅std::hashstd::nullptr_t 未实施)并由Jonathan Wakely(请参阅revision267845)(以及returns zero)修复。 p>


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

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

您将编写将显示未定义行为的代码2。风险自负。好好记录一下。例如,将以下内容放在一个单独的翻译单元中:

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

这会警告您的同事并要求他们手动删除您对 std::hash&lt;std::nullptr_t&gt; 的专业化,而不是让他们遇到严重的编译错误。


1)[functional.syn]

2) 你是 only allowed 专门为程序定义类型(nullptr_­t 不是)的 std 类模板。你也可以打破单一定义规则。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 2013-09-27
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    相关资源
    最近更新 更多