basic_string
's allocatorSection: 27.4.6 [basic.string.hash] Status: C++23 Submitter: Casey Carter Opened: 2022-05-26 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [basic.string.hash].
View all issues with C++23 status.
Discussion:
27.4.6 [basic.string.hash] says:
template<> struct hash<string>; template<> struct hash<u8string>; template<> struct hash<u16string>; template<> struct hash<u32string>; template<> struct hash<wstring>; template<> struct hash<pmr::string>; template<> struct hash<pmr::u8string>; template<> struct hash<pmr::u16string>; template<> struct hash<pmr::u32string>; template<> struct hash<pmr::wstring>;-1- If
S
is one of these string types,SV
is the corresponding string view type, ands
is an object of typeS
, thenhash<S>()(s) == hash<SV>()(SV(s))
Despite that the hash value of a basic_string
object is equivalent to the hash value of a
corresponding basic_string_view
object, which has no allocator, the capability to hash a
basic_string
depends on its allocator. All of the enabled specializations have specific
allocators, which fact becomes more clear if we expand the type aliases:
template<> struct hash<basic_string<char, char_traits<char>, allocator<char>>; template<> struct hash<basic_string<char8_t, char_traits<char8_t>, allocator<char8_t>>; template<> struct hash<basic_string<char16_t, char_traits<char16_t>, allocator<char16_t>>; template<> struct hash<basic_string<char32_t, char_traits<char32_t>, allocator<char32_t>>; template<> struct hash<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>; template<> struct hash<basic_string<char, char_traits<char>, pmr::polymorphic_allocator<char>>; template<> struct hash<basic_string<char8_t, char_traits<char8_t>, pmr::polymorphic_allocator<char8_t>>; template<> struct hash<basic_string<char16_t, char_traits<char16_t>, pmr::polymorphic_allocator<char16_t>>; template<> struct hash<basic_string<char32_t, char_traits<char32_t>, pmr::polymorphic_allocator<char32_t>>; template<> struct hash<basic_string<wchar_t, char_traits<wchar_t>, pmr::polymorphic_allocator<wchar_t>>;
If the hash value doesn't depend on the allocator type, why should we care about the allocator type?
I posit that we should not, and that these ten explicit specializations should be replaced by 5 partial
specializations that enable hashing basic_string
specializations using these combinations of
character type and traits type with any allocator type.
[2022-06-21; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
[2022-07-15; LWG telecon: move to Ready]
[2022-07-25 Approved at July 2022 virtual plenary. Status changed: Ready → WP.]
Proposed resolution:
This wording is relative to N4910.
Modify 27.4.2 [string.syn], header <string>
synopsis, as indicated:
[…] // 27.4.6 [basic.string.hash], hash support template<class T> struct hash;template<> struct hash<string>; template<> struct hash<u8string>; template<> struct hash<u16string>; template<> struct hash<u32string>; template<> struct hash<wstring>; template<> struct hash<pmr::string>; template<> struct hash<pmr::u8string>; template<> struct hash<pmr::u16string>; template<> struct hash<pmr::u32string>; template<> struct hash<pmr::wstring>;template<class A> struct hash<basic_string<char, char_traits<char>, A>>; template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>; template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>; template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>; template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>; […]
Modify 27.4.6 [basic.string.hash] as indicated:
template<> struct hash<string>; template<> struct hash<u8string>; template<> struct hash<u16string>; template<> struct hash<u32string>; template<> struct hash<wstring>; template<> struct hash<pmr::string>; template<> struct hash<pmr::u8string>; template<> struct hash<pmr::u16string>; template<> struct hash<pmr::u32string>; template<> struct hash<pmr::wstring>;template<class A> struct hash<basic_string<char, char_traits<char>, A>>; template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>; template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>; template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>; template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>;-1- If
S
is one of these string types,SV
is the corresponding string view type, ands
is an object of typeS
, thenhash<S>()(s) == hash<SV>()(SV(s))