【发布时间】:2019-06-27 05:41:27
【问题描述】:
// ... // [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 被禁用。
[...] 对于任何类型
Key既不是库也不是用户 提供类模板的显式或部分特化hash、hash<Key>已禁用。
如果
H是hash的禁用特化,则这些值为假: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将是畸形的。 — 尾注 ]
因此,以下 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++ 中的一个错误。我的分析正确吗?
【问题讨论】:
-
libc++的bug报告地址是bugs.llvm.org
标签: c++ hash c++17 libc++ string-view