直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象

Using hash directly in methods from unordered_map instead of the user defined object producing the hash

本文关键字:哈希 对象 定义 用户 unordered map 方法      更新时间:2023-10-16

所以我创建了一个类,我将其用作unordered_map中的哈希

class MyClass
{
hash_type mHash = 0;
hash_type hash() { return mHash; }
bool operator!= (const MyClass& rhs) const;
bool operator== (const MyClass& rhs) const;
}
namespace std
{
template <>
struct hash<MyClass>
{
hash_type operator()(const MyClass& k) const noexcept
{
return k.hash();
}
};
}

它按预期工作,但我想添加一些功能。 我希望能够在使用查找和擦除等unordered_map函数时使用哈希本身。 现在我必须这样做:

void _erase_key(const MyClass& key) { umap.erase(key); }

但我也希望能够做到这一点:

void _erase_key(const hash_type key) { umap.erase(key); }

使用查找和擦除等方法时,是否可以以某种方式直接使用哈希而不是产生哈希的对象?

如果我理解正确,您希望有一个std::unordered_map<MyClass, Value>,以便您也可以使用hash_type进行查询,并且您有hash_type h == MyClass m是否std::hash<MyClass>{}(m) == h。这是对的吗?

这在 C++17 中是不可能的。使用 C++20,将添加透明哈希的功能。你可以在这里非常简要地阅读。这样,您的地图必须满足某些属性

  • 您的相等类型Eq必须提供成员类型Eq::is_transparent,即您必须在其中放置一个using is_transparent = some_type;。(确切的类型没有后果。
  • 类型Eq的对象必须提供重载来比较要使用的所有可能的类型组合。 即为(MyClass, MyClass)(MyClass, hash_type)提供重载。
  • 您的哈希类型Hash必须提供成员类型Hash::transparent_key_equal,因此再次using transparent_key_equal = some_type;放入其中。
  • 类型Hash的对象必须对要使用的每种类型都可调用。 即您必须对MyClasshash_type都有一个operator()重载。

对于Eq,如果您为适当的类型提供可公开访问的operator==,则可以使用std::equal_to<>(请注意空菱形!这不是unordered_map的默认值。

据我所知,std::hash没有analagon,因此您必须为此添加自己的类型并将其提供给地图。

在 C++20 之前,如果您想保留密钥类型,您唯一能做的就是编写从hash_typeMyClass的转换。

但我感觉到一个基本问题,即如果两个MyClass对象具有相同的哈希值,则它们视为相同。如果这是无意的,您应该真正解决此问题。如果是有意为之,请确保operator==(MyClass, MyClass)也只比较哈希。

在后一种情况下,有一个简单的问题解决方法。将地图更改为std::unordered_map<hash_type, Value>,并对用于查询地图的每个MyClass进行哈希处理。如果您需要反向查找以从哈希中获取MyClass,如果可能的话,请编写一个从hash_typeMyClass的转换函数,否则添加另一个std::unordered_map<hash_type, MyClass>,在其中存储您曾经使用过的MyClass类型的每个对象。