Reputation: 20629
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>; // ...
Only for the four "common" basic_string_view
s are specializations of hash
enabled. The other basic_string_view
s have their hash
es disabled.
Per [unord.hash]/2:
[...] For any type
Key
for which neither the library nor the user provides an explicit or partial specialization of the class templatehash
,hash<Key>
is disabled.
Per [unord.hash]/4:
If
H
is a disabled specialization ofhash
, these values are false:is_default_constructible_v<H>
,is_copy_constructible_v<H>
,is_move_constructible_v<H>
,is_copy_assignable_v<H>
, andis_move_assignable_v<H>
. Disabled specializations ofhash
are not function object types. [ Note: This means that the specialization of hash exists, but any attempts to use it as aHash
will be ill-formed. — end note ]
Therefore, the following Minimal Reproducible Example should not compile because it attempts to default construct a disabled specialization of 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;
}
However, this compiles fine on Clang 8.0.0. Digging down the source of libc++, we 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());
}
};
So libc++ actually enables hash
for all basic_string_view
s.
Therefore, I conclude that this is a bug in libc++. Is my analysis correct?
Upvotes: 1
Views: 291
Reputation: 16690
You appear to be correct. Libc++ correctly disables your hash for std::basic_string
, but not for std::basic_string_view
.
Later: Fixed for LLVM 9.0
Upvotes: 4