繁体   English   中英

如何直接使用key作为std :: unordered_map的哈希?

[英]How to directly use key as hash for std::unordered_map?

我的std::unordered_map中的键是boost::uuids::uuid s,因此128位哈希被认为是唯一的。 但是,编译器无法知道,因此说明了这一点。

error C2338: The C++ Standard doesn't provide a hash for this type.

如何使地图将密钥用作哈希值? 顺便说一句, std::size_t在我的系统上被定义为unsigned int __w64 ,我认为它只涉及64位。

您始终需要提供将键映射到哈希值的函数对象,即使此映射是标识。 您可以为std::hash<boost::uuids::uuid>定义一个特殊化,并让std::unordered_map<K, V>自动选择这个,或者您可以使用附加的模板参数参数化无序映射。功能对象类型。 除了哈希之外,还需要相等操作,但默认情况下,使用operator==()可能没问题。

也就是说,除非您的系统具有内置的128位整数类型,否则哈希值将不接受128位整数。 哈希值需要是std::size_t才能与标准的无序容器一起使用。 完整的std::hash<T>特殊化要求列表在20.8.12 [unord.hash]中列出:

  1. std::hash<X>需要是默认的可构造,复制可构造和复制可分配。
  2. std::hash<X>需要可以交换。
  3. 它需要为键类型提供两个嵌套类型argument_type为散列值类型提供result_type ,后者与std::size_t相同。
  4. 对于函数,关系k1 == k2 => h(k1) == h(k2)需要为真,其中h是散列函数对象。

因此,您需要按照以下方式定义一些内容:

namespace std {
    template <>
    struct hash<boost::uuids::uuid>
    {
        typedef boost::uuids::uuid argument_type;
        typedef std::size_t        result_type;
        std::size_t operator()(boost::uuid::uuid key) const {
            return transform_to_size_t(key);
        }
    };
}

其中transform_to_size_t()是您需要提供的实际转换。 };

你需要为boost::uuids::uuid类型提供一个哈希函数。 由于它是唯一的,您可以使用stl标识。

这是unordered_map的声明。

template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;

我认为最简单的方法是为这些类型实现std::hash的特化,它返回相同的输入:

namespace std
{
    template<>
    struct hash<Foo>
    {
        Foo operator(const Foo& foo)
        {
            return foo;
        }
    };
}

假设示例中的类型Foo可以隐式转换为std::size_t

在您的情况下,类型是128位GUID, std::size_t使用32位或64位。 您可以将64位GUID拆分为64/32位的部分,并组合这些值。

我发现无法使用UUID作为std::unordered_map键,因为UUID是128位长,而映射的散列是std::size_t ,它只能容纳64位。

相反,我只删除了64位ID的真实128位UUID,它们可以存储在uint64_t类型中,并且本身由标准库的容器支持。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM