微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将 std::unordered_multiset 与自定义类一起使用?

如何解决如何将 std::unordered_multiset 与自定义类一起使用?

我正在尝试声明一个 unordered_multiset,它将包含自定义类的对象,但我找不到任何示例。根据文档,我似乎需要在类中声明一个 operator==,以及散列函数operator() const),根据文档:

  1. 接受类型为 Key 的单个参数。
  2. 返回一个 std::size_t 类型的值,表示参数的哈希值。
  3. 调用时不抛出异常。
  4. 对于两个相等的参数 k1 和 k2,std::hash<Key>()(k1) == std::hash<Key>()(k2)
  5. 对于不相等的两个不同参数 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
}

ma​​in.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;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。