【问题标题】:How to define a Hash class for custom std::basic_string<> specialization class just like std::string?如何像 std::string 一样为自定义 std::basic_string<> 专业化类定义哈希类?
【发布时间】:2018-10-08 00:59:51
【问题描述】:

我有一个std::basic_string 的特化,比如string_t,它与std::string 相同,除了第三个模板参数是我的自定义分配器。

std::basic_string<>

问题:我应该如何使用 C++ 标准库中已经提供的散列函子为这个专业定义一个散列函子类?

我知道如何定义一个哈希函子,但我不知道如何利用std 中现有的std::hash&lt;..&gt; 函子来定义我的自定义函子。我犹豫是否要编写自己的哈希操作,因为我知道它是在重新发明轮子,而且不太可能比 std::hash&lt;std::string&gt; 更好,因为 string_tstd::string 之间的唯一区别只是分配器。

cppreference 有一些示例,但它们对我没有多大帮助 - 我不想使用我的 string_t 对象的 c_str() 方法构造一个临时的std::string 对象,只是为了将临时对象提供给@987654334 @ 获取哈希值,因为它需要分配临时堆内存。

我正在使用 C++14,我想坚持使用标准库。

【问题讨论】:

  • 在 C++17 中你可以使用 std::hash&lt;std::string_view&gt;
  • @Caleth 确实,但我没有 C++17 并且有一些外部约束。我什至写了我的自定义 string_view。
  • 您尚未说明您将使用此哈希的目的。这是一个至关重要的问题。如果您打算使用它将字符串存储到标准散列容器(std::unordered_map,std::unordered_set)中,那么您的散列函数可以很简单,因为这里对低碰撞概率和均匀分布没有严格要求(尽管它是如果是这样就更好了)。如果您要将它用于加密或低冲突概率要求,那么它会变得更加复杂。
  • @BJovke 我将为散列容器使用散列。
  • @Leedehai 好吧,在这种情况下,您可以将字符串的缓冲区转换为,例如,char32_t 的数组(最后一个带有填充的元素),对所有值进行异或运算并将结果提供给 @ 987654337@.

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


【解决方案1】:

问题:我应该如何使用 C++ 标准库中已经提供的散列函子为这个特化定义一个散列函子类?

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

解决方法:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 2021-10-18
    • 2023-01-03
    • 1970-01-01
    相关资源
    最近更新 更多