libc++ 是否为太多basic_string_view提供了哈希专用化?

Is libc++ providing hash specialization for too many basic_string_view's?

本文关键字:哈希 专用 view 是否 太多 basic string libc++      更新时间:2023-10-16

per [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_view S是启用hash的专业。另一个basic_string_view S已禁用hash ES。

per [unord.hash]/2:

[...]对于任何类型的 Key 提供类模板的明确或部分专业化 hashhash<Key>被禁用。

per [unord.hash]/4:

如果Hhash的残疾人专业化,这些值是false: is_­default_­constructible_­v<H>is_­copy_­constructible_­v<H>is_­move_­constructible_­v<H>is_­copy_­assignable_­v<H>is_­move_­assignable_­v<H>hash的残障专业是 不函数对象类型。[注意:这意味着 存在Hash的专业化,但是任何尝试将其用作Hash的尝试 将是不良的。&mdash; end Note ]

因此,以下最小可重复的示例不应编译,因为它试图默认构建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上罚款。挖掘libc 的来源,我们看到:

// [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());
    }
};

SO LIBC 实际上启用了所有basic_string_views。

hash

因此,我得出结论,这是libc 中的一个错误。我的分析正确吗?

您似乎是正确的。libc 正确禁用您的 std::basic_string哈希,但不能为 std::basic_string_view

稍后:修复了LLVM 9.0