簡體   English   中英

GCC 和 Clang 不編譯 std::hash<std::nullptr_t> 在 C++17 中

[英]GCC and Clang don't compile std::hash<std::nullptr_t> in C++17

https://en.cppreference.com/w/cpp/utility/hash上說,自從 C++17

每個聲明模板 std::hash 的標准庫頭都為 std::nullptr_t 和所有 cv 非限定算術類型(包括任何擴展整數類型)、所有枚舉類型和所有指針類型提供了 std::hash 的啟用特化。

所以,一個 C++17 兼容的編譯器應該編譯這個小程序:

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

但是,GCC 和 Clang 都報告錯誤,指出std::hash<std::nullptr_t>的默認構造函數已(隱式)刪除。 請參閱此處此處自行驗證。

Visual Studio會編譯它。 顯然它返回0 672807365

Q1: GCC 和 Clang 是否仍然缺少這個 C++17 特性,誠然這不是一個高優先級的特性? 或者我錯過了什么?

Q2:我可以自己專門化它並像 Visual Studio 一樣返回0 672807365嗎? 其他一些值,例如一些素數,不是更適合將它與其他散列相結合嗎?


更新

由於我有限的匯編知識,我認為 Visual Studio 正在返回0 事實上,它返回672807365eax的值)。 所以,我的第二個問題基本上是自己回答的:我不會在我的專業中返回0來解決這個錯誤。

這個程序正確嗎?

cppreference.com 是對的。 來自最新的 C++ 標准草案:

[unord.hash]/2

如下所述,散列的每個特化要么被啟用,要么被禁用。 [...] 每個聲明模板散列的標頭都為nullptr_t和所有 cv 非限定算術、枚舉和指針類型提供了啟用的hash nullptr_t

由於<functional>聲明了hash模板1 ,它必須為std::hash<std::nullptr_t>提供一個啟用的std::hash<std::nullptr_t> 任何符合 C++17 的實現都應該接受您的示例程序


為什么不是呢?

C++17 還很年輕,一些微妙的特性可能在最近的編譯器上仍然缺失或有問題。 請放心,您的 MCVE 已被 gcc 和 clang 在其開發/實驗分支中接受。

但是我們找不到接受它的 GCC 開發版本; 這就是為什么Lightness Races in Orbit (參見std::hashstd::nullptr_t未實現)提出錯誤報告並由Jonathan Wakely修復(參見修訂版267845 )(並返回零)的原因。


如何在等待實現修復的同時修復您的程序?

我可以自己專門化它並像 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<std::nullptr_t>專業化,而不是讓他們出現令人討厭的編譯錯誤。


1)參見[functional.syn]

2)只能為程序定義的類型( nullptr_t不是)專門化std類模板。 你也可以打破一個定義規則。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM