[英]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
。 事實上,它返回672807365
( eax
的值)。 所以,我的第二個問題基本上是自己回答的:我不會在我的專業中返回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.