简单代码:
#include <unordered_map>
int main()
{
std::unordered_map<const int, int> m;
std::unordered_map<const int, int> m1 = m;
}
产生复杂的编译错误消息:
错误C2280'std :: hash <_Kty> :: hash(void)':尝试引用 功能已删除
基本上在内部表示unordered_map
的人并不期望密钥是恒定的
PS : 我已经读过answer的类似问题:
关联容器仅将(key,value)对公开为 std :: pair,因此在 密钥类型是多余的。
但是它并没有解释为什么带有const键的哈希图实际上是不可用的,以及如何规避这一问题
答案 0 :(得分:7)
类型
std::unordered_map<const int, int>
使用默认的第三个参数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>{};
}
或者您可以明确声明您的哈希值:
std::unordered_map<const int, int, std::hash<int>>
或者您可以删除键中的const(因为它无效):
std::unordered_map<int, int>
附录:
已删除表示删除了非专业std::hash
的构造函数:
template <typename T>
struct hash
{
hash() = delete;
hash(const hash) = delete;
// more deleted methods
};
“删除”表示它不存在(既不是用户提供的也不是默认值)。
您可以在cppreference上看到这一点,他们使用启用/禁用的术语:
对于库和用户都未为其提供启用的特殊化std :: hash的每种类型Key,该特殊化存在且被禁用。
由于库未提供std::hash<const int>
,因此除非用户提供,否则它将被禁用。接下来,文字说明什么是 disabled :
禁用的专业不能满足哈希,[...] std :: is_default_constructible_v,std :: is_copy_constructible_v [...]都是错误的。换句话说,它们存在,但无法使用。
因此,这些构造函数必须不可用(删除它们是最好的方法)。