[英]Does unordered_set not support `unordered_set<vector<int>>` or `unordered_set<pair<int,int>>`?
unordered_set<pair<int,int>> vis;
unordered_set<vector<int>> vis;
他们都错了,但如果我把它们改成
set<vector<int>> vis;
set<pair<int,int>> vis;
那么他们是正确的。 为什么?
int test()
{
unordered_set<pair<int,int>> vis;
return 0;
}
编译错误:
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.
默认情况下,没有。 对于unordered_set
,它需要能够 hash 对象,并且std::pair
和std::vector
没有默认的 hash 实现。 有两种典型的方法可以做到这一点; 为您提供自己的Hash
类型,或为这些类型实现std::hash
函数。 让我们看看两者。
首先,这是std::unordered_set
的定义方式:
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>>
的特化不存在。 所以我们可以提供它:
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>
来实现 hash,但是您可以随意实现它。
或者,您可以提供自己的结构而不是实现std::hash
,然后在定义unordered_set
object 时必须声明它:
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 中,您可以在未计算的上下文中使用 lambda,例如decltype
,因此以下内容也是有效的:
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;
}
std::unordered_set
对其键类型进行散列,因此std::hash
的特化需要可用于键类型,否则您需要在声明std::unordered_set
时指定自己的散列 function 。 std::pair
或std::vector
没有std::hash
的默认特化。
另一方面, std::set
不是 hash 的关键。 它默认使用operator<
比较键值, std::pair
和std::vector
都实现了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.