简体   繁体   English

如何像std :: string一样为自定义std :: basic_string <>专业化类定义哈希类?

[英]How to define a Hash class for custom std::basic_string<> specialization class just like std::string?

I have a specialization of std::basic_string , say, string_t , and it the same as std::string except that the third template argument is my custom allocator. 我有std::basic_string ,例如string_t ,它 std::string相同,除了第三个模板参数是我的自定义分配器。

std::basic_string<> std :: basic_string <>

Question: How should I define a hash functor class for this specialization using hash functors already provided in C++ standard library? 问题:我应该如何使用C ++标准库中已经提供的哈希函子来为此专业定义哈希函子类?

I know how to define a Hash functor, but I don't know how to utilize existing std::hash<..> functors in std to define my custom one. 我知道如何定义一个散列函数对象,但我不知道如何利用现有std::hash<..>的函子std定义我的自定义一个。 I hesitate to write my own hashing operations, knowing it is reinventing the wheel and is unlikely to be better than std::hash<std::string> , since the only difference between string_t and std::string is just the allocator. 我很犹豫地编写自己的哈希操作,因为它知道它是在重新发明轮子,并且不可能比std::hash<std::string>更好,因为string_tstd::string之间的唯一区别只是分配器。

cppreference has some examples but they don't help me much - I don't want to construct a temporary std::string object using my string_t object's c_str() method only to feed the temporary object into std::hash<std::string> to get the hash value, because it entails allocating temporary heap memory. cppreference有一些示例,但它们对我没有太大帮助-我不想使用我的string_t对象的c_str()方法构造一个临时std::string对象,而只是将临时对象输入std::hash<std::string>来获取哈希值,因为它需要分配临时堆内存。

I'm using C++14 and I want to stick to standard library. 我正在使用C ++ 14,我想坚持使用标准库。

Question: How should I define a hash functor class for this specialization using hash functors already provided in C++ standard library? 问题:我应该如何使用C ++标准库中已经提供的哈希函子来为此专业定义哈希函子类?

The short and sad answer is that there is no way to do this. 简短而悲伤的答案是,没有办法做到这一点。 The standard library does not offer hash functions for sequences of integral types. 标准库不提供整数类型序列的哈希函数。

Workarounds: 解决方法:

boost::hash is superior in every way to std::hash . boost::hash在所有方面都优于std::hash I would suggest you define your std::hash specialisation in terms of it. 我建议您根据它定义std::hash专门化。

Furthermore, if you can, specify boost::hash<> as the hashing function for all unordered containers. 此外,如果可以的话,请为所有无序容器指定boost::hash<>作为哈希函数。 You'll never regret it. 您永远不会后悔。 std::hash is a half-formed library. std::hash是半格式的库。

#include <string>
#include <cassert>
#include <unordered_set>
#include <boost/functional/hash.hpp>

struct my_alloc ...

using my_string = std::basic_string<char, std::char_traits<char>, my_alloc>;
std::size_t hash_value(::my_string const& s)
{
            return boost::hash_range(s.begin(), s.end());
}

namespace std {
    template<> struct hash<::my_string> 
    {
        std::size_t operator()(::my_string const& s) const
        {
            return hash_value(s);
        }
    };
}

int main()
{
    auto x = my_string("Hello");

    using Set1 = std::unordered_set<my_string, boost::hash<my_string>>;
    auto set1 = Set1 { x };

    auto h = std::hash<my_string>();
    auto hh = h(x);
    assert(hh == hash_value(x));
    return int(hh);
}

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

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