【问题标题】:Are there no specializations of std::hash for standard containers?标准容器没有 std::hash 的特化吗?
【发布时间】:2011-11-06 13:41:44
【问题描述】:

just 发现自己无法简单地使用 a 有点惊讶

std::unordered_set<std::array<int, 16> > test;

因为似乎没有std::hash 专门用于std::arrays。这是为什么?还是我根本没找到?如果确实没有,是否可以简化以下实现尝试?

namespace std
{
    template<typename T, size_t N>
    struct hash<array<T, N> >
    {
        typedef array<T, N> argument_type;
        typedef size_t result_type;

        result_type operator()(const argument_type& a) const
        {
            hash<T> hasher;
            result_type h = 0;
            for (result_type i = 0; i < N; ++i)
            {
                h = h * 31 + hasher(a[i]);
            }
            return h;
        }
    };
}

我真的觉得这应该以某种方式成为标准库的一部分。

【问题讨论】:

  • 真的没有,只有std::string和朋友有这个特权。如果我说这是因为 C++ 在标准数据结构方面将自己拖向当前最先进技术的努力还没有完成全部工作,我真的会不受欢迎吗?实际上,模板没有任何必需的hash 特化(这反过来又要求它们的模板参数是可散列的)。唯一需要的特化是内置类型和四个具体字符串类。所以我怀疑那里画了一条线。
  • stringu16stringu32stringwstring(在 C++11 中为 21.6)。我想说pairtuple 应该是次高优先级目标,然后是标准容器,然后是由可散列成员组成的任何聚合类型的默认散列。
  • 显然string 散列器需要一个内部函数来散列内存块。我想知道为什么他们不需要实现直接公开它?
  • @FredOverflow:我会查找boost::hash_combine 的代码,是否要在集合上实现散列。
  • @nemo 没有人把它写成给委员会的论文。只有当有人足够关心以实现它时,事情才会进入标准。

标签: c++ arrays c++11 hash-function unordered-set


【解决方案1】:

不是答案,而是一些有用的信息。 C++11 标准的 2 月草案指定 std::hash 专门用于这些类型:

  • error_code § 19.5.5
  • bitset&lt;N&gt; § 20.5.3
  • unique_ptr&lt;T, D&gt; § 20.7.2.36
  • shared_ptr&lt;T, D&gt; § 20.7.2.36
  • type_index § 20.13.4
  • string § 21.6
  • u16string § 21.6
  • u32string § 21.6
  • wstring § 21.6
  • vector&lt;bool, Allocator&gt; § 23.3.8
  • thread::id § 30.3.1.1

所有这些类型:§ 20.8.12

template <> struct hash<bool>;
template <> struct hash<char>;
template <> struct hash<signed char>;
template <> struct hash<unsigned char>;
template <> struct hash<char16_t>;
template <> struct hash<char32_t>;
template <> struct hash<wchar_t>;
template <> struct hash<short>;
template <> struct hash<unsigned short>;
template <> struct hash<int>;
template <> struct hash<unsigned int>;
template <> struct hash<long>;
template <> struct hash<long long>;
template <> struct hash<unsigned long>;
template <> struct hash<unsigned long long>;
template <> struct hash<float>;
template <> struct hash<double>;
template <> struct hash<long double>;
template<class T> struct hash<T*>;

【讨论】:

    【解决方案2】:

    我不确定为什么标准库没有包含这个,但是 Boost 对由可散列类型组成的各种事物都有散列。这里的关键函数是hash_combine,欢迎您从boost/functional/hash/hash.hpp复制。

    使用hash_combine,Boost 派生出range_hash(只是组合范围内每个元素的哈希),以及对和元组哈希。 range_hash 反过来可用于散列任何可迭代容器。

    【讨论】:

    • 是的,range_hash 听起来应该是标准。
    猜你喜欢
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 2016-06-24
    • 1970-01-01
    相关资源
    最近更新 更多