【问题标题】:Is libc++ providing hash specialization for too many basic_string_view's?libc++ 是否为太多的 basic_string_view 提供哈希专业化?
【发布时间】:2019-06-27 05:41:27
【问题描述】:

[string.view.synop]:

// ...

// [string.view.hash], hash support
template<class T> struct hash;
template<> struct hash<string_view>;
template<> struct hash<u16string_view>;
template<> struct hash<u32string_view>;
template<> struct hash<wstring_view>;

// ...

仅对四个“普通”basic_string_views 启用了 hash 的特化。其他basic_string_views 的hashes 被禁用。

[unord.hash]/2

[...] 对于任何类型 Key 既不是库也不是用户 提供类模板的显式或部分特化 hashhash&lt;Key&gt; 已禁用。

[unord.hash]/4

如果Hhash 的禁用特化,则这些值为假: is_­default_­constructible_­v&lt;H&gt;, is_­copy_­constructible_­v&lt;H&gt;, is_­move_­constructible_­v&lt;H&gt;is_­copy_­assignable_­v&lt;H&gt;is_­move_­assignable_­v&lt;H&gt;hash 的禁用专业化是 不是函数对象类型。 [ 注意: 这意味着 散列的专门化存在,但任何尝试将其用作Hash 将是畸形的。 — 尾注 ]

因此,以下 Minimal Reproducible Example 不应编译,因为它试图默认构造一个禁用的 hash 特化:

#include <string_view>

// trait is a char trait distinct from std::char_traits<char>
struct trait :std::char_traits<char> {
    using char_traits<char>::char_traits;
};

int main()
{
    [[maybe_unused]] std::hash<std::basic_string_view<char, trait>> x;
}

但是,这会在 Clang 8.0.0 上编译 fine。深挖libc++源码,我们see

// [string.view.hash]
template<class _CharT, class _Traits>
struct _LIBCPP_TEMPLATE_VIS hash<basic_string_view<_CharT, _Traits> >
    : public unary_function<basic_string_view<_CharT, _Traits>, size_t>
{
    _LIBCPP_INLINE_VISIBILITY
    size_t operator()(const basic_string_view<_CharT, _Traits> __val) const _NOEXCEPT {
        return __do_string_hash(__val.data(), __val.data() + __val.size());
    }
};

所以 libc++ 实际上为所有basic_string_views 启用了hash

因此,我断定这是 libc++ 中的一个错误。我的分析正确吗?

【问题讨论】:

标签: c++ hash c++17 libc++ string-view


【解决方案1】:

你似乎是对的。 Libc++ 正确禁用了 std::basic_string 的哈希,但不适用于 std::basic_string_view

稍后:已针对 LLVM 9.0 修复

【讨论】:

  • 是吗?当我将basic_string_view 更改为basic_string 时,相同的代码编译fine
  • 它不适用于我使用 ToT clang 和 libc++ - 如果您将 Wandbox 设置更改为“Clang HEAD”,它将无法编译。
  • 感谢您的信息!在声明错误之前,我绝对应该检查最新版本。
猜你喜欢
  • 2021-01-01
  • 2011-06-25
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 2022-11-15
  • 2011-03-04
  • 2019-08-19
  • 1970-01-01
相关资源
最近更新 更多