【问题标题】:How to copy unordered_map with a const key?如何使用 const 键复制 unordered_map?
【发布时间】:2019-03-11 04:26:51
【问题描述】:

简单代码:

#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 在其内部并不期望密钥是恒定的

附言: 我已经阅读了answer 的类似问题:

关联容器仅将 (key,value) 对公开为 std::pair,所以附加的 const 键类型是多余的。

但它没有解释为什么带有 const 键的 hashmap 实际上无法使用以及如何规避这个问题

【问题讨论】:

  • 无关:unsorted_map 中的键无论如何都是 const。想一想,如果任何 shmuck 可以随时更改密钥,那么保持正确的顺序是多么令人讨厌。

标签: c++ stl


【解决方案1】:

类型

std::unordered_map<const int, int> 

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

复制 unordered_set 时需要工作哈希。制作一个有效的哈希:

  1. 您可以自己专门化std::hash&lt;const int&gt;,使其不再被删除:

    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> 
    

附录:

Deleted表示非特化std::hash的构造函数被删除:

template <typename T>
struct hash
{
   hash() = delete;
   hash(const hash) = delete;
   // more deleted methods
};

“已删除”表示它不存在(既不是用户提供的也不是默认的)。

你可以在cppreference看到这个,他们使用启用/禁用的术语:

对于库和用户都没有为其提供启用的特化 std::hash 的每个类型 Key,该特化存在并且被禁用。

由于库不提供std::hash&lt;const int&gt;,因此除非用户提供,否则它会被禁用。接下来,文字解释了disabled是什么:

禁用的特化不满足 Hash,[...] std::is_default_constructible_v,std::is_copy_constructible_v [...] 都是假的。换句话说,它们存在,但不能使用。

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

【讨论】:

    猜你喜欢
    • 2011-04-29
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2011-12-28
    相关资源
    最近更新 更多