问题描述
我正在尝试声明一个 unordered_multiset,它将包含自定义类的对象,但我找不到任何示例。根据文档,我似乎需要在类中声明一个 operator==
,以及散列函数(operator() const
),根据文档:
- 接受类型为
Key
的单个参数。 - 返回一个
std::size_t
类型的值,表示参数的哈希值。 - 调用时不抛出异常。
- 对于两个相等的参数 k1 和 k2,
std::hash<Key>()(k1) == std::hash<Key>()(k2)
。 - 对于不相等的两个不同参数 k1 和 k2,
std::hash<Key>()(k1) == std::hash<Key>()(k2)
应该非常小,接近1.0/std::numeric_limits<std::size_t>::max()
。
代码看起来很简单:
Class MyClass:
// comparator
bool MyClass::operator ==(const MyClass b) const {
return (string == b.getString()); // compares two strings
}
// hash operation
size_t MyClass::operator()() const {
return hash<string>()(string); // bases the hash on the string
}
main.cpp:
unordered_multiset<MyClass> s1;
// Also tried: unordered_multiset<MyClass,std::hash<MyClass>,std::equal_to<MyClass>> s1;
但是,在 unordered_multiset
的实例化中,编译器 (GCC) 会抱怨哈希函数(Tupla 是 MyClass 的名称,有 1000 多行,我包括了其中的一些):
error: use of deleted function ‘std::unordered_multiset<_Value,_Hash,_Pred,_Alloc>::unordered_multiset() [with _Value = Tupla; _Hash = std::hash<Tupla>; _Pred = std::equal_to<Tupla>; _Alloc = std::allocator<Tupla>]’
78 | unordered_multiset<Tupla> s1;
| ^~
/usr/include/c++/10/bits/unordered_set.h:949:7: note: ‘std::unordered_multiset<_Value,_Alloc>::unordered_multiset() [with _Value = Tupla; _Hash = std::hash<Tupla>; _Pred = std::equal_to<Tupla>; _Alloc = std::allocator<Tupla>]’ is implicitly deleted because the default deFinition would be ill-formed:
949 | unordered_multiset() = default;
/usr/include/c++/10/bits/unordered_set.h:949:7: error: use of deleted function ‘std::_Hashtable<_Key,_Value,_Alloc,_ExtractKey,_Equal,_H1,_H2,_RehashPolicy,_Traits>::_Hashtable() [with _Key = Tupla; _Value = Tupla; _Alloc = std::allocator<Tupla>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<Tupla>; _H1 = std::hash<Tupla>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true,true,false>]’
In file included from /usr/include/c++/10/unordered_set:46,/usr/include/c++/10/bits/hashtable.h:451:7: note: ‘std::_Hashtable<_Key,false>]’ is implicitly deleted because the default deFinition would be ill-formed:
451 | _Hashtable() = default;
也提到了分配器是 unordered_multiset 的先决条件,但我既不理解也不知道是否应该(或如何)包含它。
我错过了什么?
解决方法
我猜你可以用你的结构替换字符串:
#include <bits/stdc++.h>
using namespace std;
// Custom Hash Functor that will compute the hash on the
// passed string objects length
struct StringHashBySize {
public:
size_t operator()(const std::string & str) const {
int size = str.length();
return std::hash<int>()(size);
}
};
// Custom comparator that compares the string objects by length
struct StringEqualBySize {
public:
bool operator()(const std::string & str1,const std::string & str2) const {
if (str1.length() == str2.length())
return true;
else
return false;
}
};
int main() {
// Declaring unordered_multiset with Custom Hash Function and comparator
unordered_multiset<std::string,StringHashBySize,StringEqualBySize> multiset;
return 0;
}
,
最简单的方法可能是哈希实现的辅助类:
struct MyClassHash
{
const std::hash<std::string> m_stringHash {};
size_t operator()(const MyClass& value) const
{
return m_stringHash(value.getString());
};
};
并将其用于散列:
std::unordered_multiset<MyClass,MyClassHash> s1;
顺便说一句,我建议将参数作为对 operator==
的引用传递,而不是通过复制:
bool operator==(const MyClass& other) const;