关于C++中的unordered_map和unordered_set不能直接以pair作为键名的问题

在 C++ STL 中,不同于有序的 std::mapstd::set 是基于红黑树实现的,std::unordered_mapstd::unordered_set 是基于哈希实现的,在不要求容器内的键有序,仅要求查找效率较高时,哈希实现的后者时更为合适的,哈希表的运用也经常出现在各种算法题中。

但是,我们知道,既然是基于哈希实现的,那么就需要指定哈希函数。对于内置的数据类型如 intfloatchar 等,STL 库已经帮助我们内置了常用的哈希函数。因此通常,我们在使用这些数据类型组成的 unordered_map 和 unordered_set 可以不再指定哈希函数,直接用默认的。这在 unordered_map 的类模板定义中也可看到:

template < class Key,            //容器中存储元素的类型
           class Hash = hash<Key>,    //确定元素存储位置所用的哈希函数
           class Pred = equal_to<Key>,   //判断各个元素是否相等所用的函数
           class Alloc = allocator<Key>   //指定分配器对象的类型
           > class unordered_set;

在这些参数重,只有第一个参数是没有默认值的。也就是说,在我们创建 intchar 等内置类型的 unordered_set 时只需要传入存储在容器中的类型即可。

但是,对于没有默认的哈希函数的类型,如自定义的 class 类型,pair 类型等,我们就必须自己指定一个哈希函数。这也是为什么直接构建 pair 类型的 unordered_set 如 unordered_set<pair<int, int>> uset 会出现问题(不会在声明时报错,而是在 insert 等操作时)。

对于这种情况,我们只需要将上面的第二个参数:确定元素存储位置所用的哈希函数,也在声明时传入就行了。关于哈希函数的选择,不同的情景会有所不同。这里笔者给出一个最简单的针对 pair 类型的哈希函数。

struct SimplePairHash {
    std::size_t operator()(const std::pair<int, int>& p) const {
        return p.first ^ p.second;
    }
};

在声明时直接将其传入即可:

std::unordered_set<std::pair<int, int>, SimplePairHash> S;
S.insert(std::make_pair(0, 1));

Ref :

https://stackoverflow.com/questions/21288345/unordered-set-of-pairs-compilation-error

https://blog.csdn.net/pineappleKID/article/details/108341064

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐