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

时间:2018-04-27 08:08:23

标签: c++ string hash c++14

我有std::basic_string的专业化,比方说,string_t,除了第三个模板参数是我的自定义分配器之外,还有相同 std::string

std::basic_string<>

问题:如何使用C ++标准库中已提供的散列函数为此专门化定义散列仿函数类?

我知道如何定义Hash仿函数,但我不知道如何利用std::hash<..>中的现有std仿函数来定义我的自定义仿函数。我不愿意编写自己的哈希操作,知道它正在重新发明轮子并且不可能比std::hash<std::string>更好,因为string_tstd::string之间的唯一区别就是分配器。 / p>

cppreference有一些示例,但它们对我帮助不大 - 我不想使用我的std::string对象构建临时string_t对象。 s c_str()方法仅用于将临时对象提供给std::hash<std::string>以获取哈希值,因为它需要分配临时堆内存。

我使用的是C ++ 14,我想坚持使用标准库。

1 个答案:

答案 0 :(得分:4)

  

问题:如何使用C ++标准库中已提供的散列函数为此专门化定义散列仿函数类?

简短而悲伤的答案是没有办法做到这一点。标准库不为整数类型的序列提供散列函数。

解决方法:

boost::hash在各个方面都优于std::hash。我建议您根据它来定义std::hash专业化。

此外,如果可以,请指定boost::hash<>作为所有无序容器的散列函数。你永远不会后悔。 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);
}