如何使用const键复制unordered_map?

时间:2019-03-11 04:26:52

标签: c++ stl

简单代码:

#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键的哈希图实际上是不可用的,以及如何规避这一问题

1 个答案:

答案 0 :(得分:7)

类型

std::unordered_map<const int, int> 

使用默认的第三个参数std::hash<const int>。与std::hash<int>不同,此哈希类型不是标准库专用的,deleted也不是标准库专用的(如错误消息所述)。

复制unordered_set时需要工作哈希。进行有效的哈希处理:

  1. 您可以自己专门设置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>{};
    }
    
  2. 或者您可以明确声明您的哈希值:

    std::unordered_map<const int, int, std::hash<int>> 
    
  3. 或者您可以删除键中的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 [...]都是错误的。换句话说,它们存在,但无法使用。

因此,这些构造函数必须不可用(删除它们是最好的方法)。