首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >unordered_set不支持`unordered_set<vector<int>>`还是`unordered_set<pair<int,int>>`?

unordered_set不支持`unordered_set<vector<int>>`还是`unordered_set<pair<int,int>>`?
EN

Stack Overflow用户
提问于 2022-09-27 19:29:51
回答 2查看 77关注 0票数 1
代码语言:javascript
运行
复制
unordered_set<pair<int,int>> vis;
unordered_set<vector<int>> vis;

他们都错了,但如果我把他们改成

代码语言:javascript
运行
复制
set<vector<int>> vis;
set<pair<int,int>> vis;

那么他们是正确的。为什么?

代码语言:javascript
运行
复制
int test()
{
        unordered_set<pair<int,int>> vis;
        return 0;
}

编译错误:

代码语言:javascript
运行
复制
error: call to implicitly-deleted default constructor of 'unordered_set<pair<int, int>>'
        unordered_set<pair<int,int>> vis;
                                     ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/unordered_set.h:135:7: note: explicitly defaulted function was implicitly deleted here
      unordered_set() = default;
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/unordered_set.h:100:18: note: default constructor of 'unordered_set<std::pair<int, int>, std::hash<std::pair<int, int>>, std::equal_to<std::pair<int, int>>, std::allocator<std::pair<int, int>>>' is implicitly deleted because field '_M_h' has a deleted default constructor
      _Hashtable _M_h;
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable.h:414:7: note: explicitly defaulted function was implicitly deleted here
      _Hashtable() = default;
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable.h:174:7: note: default constructor of '_Hashtable<std::pair<int, int>, std::pair<int, int>, std::allocator<std::pair<int, int>>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true>>' is implicitly deleted because base class '__detail::_Hashtable_base<pair<int, int>, pair<int, int>, _Identity, equal_to<pair<int, int>>, hash<pair<int, int>>, _Mod_range_hashing, _Default_ranged_hash, _Hashtable_traits<true, true, true>>' has a deleted default constructor
    : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1822:5: note: explicitly defaulted function was implicitly deleted here
    _Hashtable_base() = default;
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1771:5: note: default constructor of '_Hashtable_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::equal_to<std::pair<int, int>>, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, true, true>>' is implicitly deleted because base class '_Hash_code_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, _Hashtable_traits<true, true, true>::__hash_cached::value>' has a deleted default constructor
  : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1373:7: note: explicitly defaulted function was implicitly deleted here
      _Hash_code_base() = default;
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1349:7: note: default constructor of '_Hash_code_base<std::pair<int, int>, std::pair<int, int>, std::__detail::_Identity, std::hash<std::pair<int, int>>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>' is implicitly deleted because base class '_Hashtable_ebo_helper<1, std::hash<std::pair<int, int>>>' has a deleted default constructor
      private _Hashtable_ebo_helper<1, _H1>,
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1096:7: note: explicitly defaulted function was implicitly deleted here
      _Hashtable_ebo_helper() = default;
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/hashtable_policy.h:1094:7: note: default constructor of '_Hashtable_ebo_helper<1, std::hash<std::pair<int, int>>, true>' is implicitly deleted because base class 'std::hash<std::pair<int, int>>' has a deleted default constructor
    : private _Tp
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/functional_hash.h:101:19: note: default constructor of 'hash<std::pair<int, int>>' is implicitly deleted because base class '__hash_enum<std::pair<int, int>>' has no default constructor
    struct hash : __hash_enum<_Tp>
                  ^
1 error generated.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-27 19:37:59

默认情况下不。对于unordered_set,它需要能够散列对象,而std::pairstd::vector没有默认的哈希实现。有两种典型的方法可以做到这一点:提供您自己的Hash类型,或者为这些类型实现std::hash函式。让我们看看这两个。

首先,std::unordered_set是这样定义的:

代码语言:javascript
运行
复制
template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;

我们感兴趣的是第二个模板参数Hash = std::hash<Key>。目前,由于不存在std::hash<std::pair<int, int>>的专门化,您的程序无法编译。所以我们可以提供:

代码语言:javascript
运行
复制
template <>
struct std::hash<std::pair<int, int>>
{
    std::size_t operator()(std::pair<int, int> p) {
        return std::hash<int>{}(p.first) ^ std::hash<int>{}(p.second);
    }
};

在这里,我将委托给std::hash<int>来实现哈希,但是您可以任意实现这个哈希。

或者,您可以提供自己的结构,而不是实现std::hash,您只需在定义unordered_set对象时声明它:

代码语言:javascript
运行
复制
struct MyHash
{
    std::size_t operator()(std::pair<int, int> p) {
        return std::hash<int>{}(p.first) ^ std::hash<int>{}(p.second);
    }
};

int main() {
    std::unordered_set<std::pair<int, int>, MyHash> mySet; // Using my own hashing class.
}

为了好玩,在C++20中,您可以在未评估的上下文(如decltype )中使用lambda,因此以下内容也是有效的:

代码语言:javascript
运行
复制
int main() {
    const auto hash = [](std::pair<int, int> p) {
        return std::hash<int>{}(p.first) ^ std::hash<int>{}(p.second);
    }

    std::unordered_set<std::pair<int, int>, decltype(hash)> mySet; 
}
票数 6
EN

Stack Overflow用户

发布于 2022-09-27 19:37:36

std::unordered_set散列其键类型,因此需要为密钥类型提供std::hash的专门化,或者在声明std::unordered_set时需要指定自己的哈希函数。std::hash对于std::pairstd::vector没有默认的专门化。

另一方面,std::set没有散列它的密钥。它比较了默认情况下使用operator<的键值,std::pairstd::vector都实现了这一点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73872919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档