使用带有数组的unordered_map作为键

时间:2017-03-09 17:22:46

标签: c++ c++11 stl unordered-map

我不明白为什么我不能拥有unordered_map作为密钥类型array<int,3>

#include <unordered_map>

using namespace std;

int main() {

   array<int,3> key = {0,1,2};

   unordered_map< array<int,3> , int >  test;
   test[key]  = 2;

   return 0;
}

我得到一个很长的错误,最相关的部分是

main.cpp:11:9: error: no match for ‘operator[]’ (operand types are std::unordered_map<std::array<int, 3ul>, int>’ and ‘std::array<int, 3ul>’)
 test[key]  = 2;
     ^

数组是否有资格成为密钥,因为它们错过了一些要求?

4 个答案:

答案 0 :(得分:8)

相关错误是

error: no match for call to '(const std::hash<std::array<int, 3ul> >) (const std::array<int, 3ul>&)'

unordered_map需要密钥的哈希值,并且它会查找std::hash的重载来执行此操作。您可以使用合适的哈希函数扩展namespace std

答案 1 :(得分:8)

<强>为什么吗

正如http://www.cplusplus.com/reference/unordered_map/unordered_map/

中所述
  

在内部,unordered_map中的元素未按任何方式排序   关于其键值或映射值的特定顺序,   但是根据它们的哈希值组织成桶以允许   通过键值快速访问各个元素(使用   平均时间复杂度恒定。)

现在根据你的问题,我们需要hash一个尚未在标准c ++内部实现的数组。

如何克服它?

因此,如果您想将array映射到某个值,则必须实现自己的std :: hash http://en.cppreference.com/w/cpp/utility/hash,您可以从C++ how to insert array into hash set?获得一些帮助。

有些解决方法

如果您可以自由使用boost,那么它可以为您提供数组和许多其他类型的散列。它基本上使用hash_combine方法,您可以查看http://www.boost.org/doc/libs/1_49_0/boost/functional/hash/hash.hpp

答案 2 :(得分:8)

您必须实现哈希。散列表取决于散列键,找到一个存储桶.C ++并不神奇地知道如何散列每个类型,在这种特殊情况下,它不知道如何默认散列3个整数的数组。您可以实现这样的简单哈希结构:

struct ArrayHasher {
    std::size_t operator()(const std::array<int, 3>& a) {
        std::size_t h = 0;

        for (auto e : a) {
            h ^= std::hash<int>{}(e)  + 0x9e3779b9 + (h << 6) + (h >> 2); 
        }
        return h;
    }   
};

然后使用它:

unordered_map< array<int,3> , int, ArrayHasher >  test;

编辑:我更改了将来自天真xor的哈希值与为此目的使用的函数组合的函数:http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html。这应该足够强大,可以实际使用。

答案 3 :(得分:2)

使用msvc14编译时出现以下错误:

  

&#34; C ++标准没有为此类型提供哈希值。&#34;

我想这是不言自明的。