简单的代码:
#include <unordered_map>
int main()
{
std::unordered_map<const int, int> m;
std::unordered_map<const int, int> m1 = m;
}
Run Code Online (Sandbox Code Playgroud)
产生复杂的编译错误消息:
错误C2280'std :: hash <_Kty> :: hash(void)':尝试引用已删除的函数
基本上unordered_map在内部表示不希望密钥保持不变
PS:我已经阅读了类似问题的答案:
关联容器仅将(key,value)对公开为std :: pair,因此键类型上的其他const是多余的。
但这并没有解释为什么带有const键的哈希图实际上是不可用的,以及如何规避此问题
类型
std::unordered_map<const int, int>
Run Code Online (Sandbox Code Playgroud)
使用默认的第三个参数std::hash<const int>。与不同的std::hash<int>是,此散列类型不是标准库专用的,而是散列类型deleted(如错误消息所述)。
复制unordered_set时,需要工作哈希。进行工作哈希:
您可以std::hash<const int>自己专门设置,以便不再删除它:
namespace std
{
// fixes it but is a bad idea - could break in future revisions of the standard
template<>
struct hash<const int> : hash<int>{};
}
Run Code Online (Sandbox Code Playgroud)或者,您可以明确声明您的哈希值:
std::unordered_map<const int, int, std::hash<int>>
Run Code Online (Sandbox Code Playgroud)或者,您可以删除键中的const(因为它无效):
std::unordered_map<int, int>
Run Code Online (Sandbox Code Playgroud)附录:
Deleted表示将非专业化的构造函数std::hash删除:
template <typename T>
struct hash
{
hash() = delete;
hash(const hash) = delete;
// more deleted methods
};
Run Code Online (Sandbox Code Playgroud)
“删除”表示它不存在(既不是用户提供的也不是默认值)。
您可以在cppreference上看到这一点,他们使用启用/禁用的术语:
对于库和用户均未为其提供启用的专业化std :: hash的每个类型Key,该专业化存在且被禁用。
由于std::hash<const int>不是库提供的,除非用户提供,否则它将被禁用。接下来,文本说明什么是禁用:
禁用的专业不能满足哈希,[...] std :: is_default_constructible_v,std :: is_copy_constructible_v [...]全部为假。换句话说,它们存在,但不能使用。
因此,这些构造函数必须不可用(删除它们是最好的方法)。
| 归档时间: |
|
| 查看次数: |
200 次 |
| 最近记录: |