@@ -4226,86 +4226,76 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- // DR 1182.
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3705. Hashability shouldn't depend on basic_string's allocator
+
+ template<typename _CharT, typename _Alloc,
+ typename _StrT = basic_string<_CharT, char_traits<_CharT>, _Alloc>>
+ struct __str_hash_base
+ : public __hash_base<size_t, _StrT>
+ {
+ size_t
+ operator()(const _StrT& __s) const noexcept
+ { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); }
+ };
#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
/// std::hash specialization for string.
- template<>
- struct hash<string>
- : public __hash_base<size_t, string>
- {
- size_t
- operator()(const string& __s) const noexcept
- { return std::_Hash_impl::hash(__s.data(), __s.length()); }
- };
-
- template<>
- struct __is_fast_hash<hash<string>> : std::false_type
+ template<typename _Alloc>
+ struct hash<basic_string<char, char_traits<char>, _Alloc>>
+ : public __str_hash_base<char, _Alloc>
{ };
/// std::hash specialization for wstring.
- template<>
- struct hash<wstring>
- : public __hash_base<size_t, wstring>
- {
- size_t
- operator()(const wstring& __s) const noexcept
- { return std::_Hash_impl::hash(__s.data(),
- __s.length() * sizeof(wchar_t)); }
- };
+ template<typename _Alloc>
+ struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Alloc>>
+ : public __str_hash_base<wchar_t, _Alloc>
+ { };
- template<>
- struct __is_fast_hash<hash<wstring>> : std::false_type
+ template<typename _Alloc>
+ struct __is_fast_hash<hash<basic_string<wchar_t, char_traits<wchar_t>,
+ _Alloc>>>
+ : std::false_type
{ };
#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
#ifdef _GLIBCXX_USE_CHAR8_T
/// std::hash specialization for u8string.
- template<>
- struct hash<u8string>
- : public __hash_base<size_t, u8string>
- {
- size_t
- operator()(const u8string& __s) const noexcept
- { return std::_Hash_impl::hash(__s.data(),
- __s.length() * sizeof(char8_t)); }
- };
-
- template<>
- struct __is_fast_hash<hash<u8string>> : std::false_type
+ template<typename _Alloc>
+ struct hash<basic_string<char8_t, char_traits<char8_t>, _Alloc>>
+ : public __str_hash_base<char8_t, _Alloc>
{ };
#endif
/// std::hash specialization for u16string.
- template<>
- struct hash<u16string>
- : public __hash_base<size_t, u16string>
- {
- size_t
- operator()(const u16string& __s) const noexcept
- { return std::_Hash_impl::hash(__s.data(),
- __s.length() * sizeof(char16_t)); }
- };
-
- template<>
- struct __is_fast_hash<hash<u16string>> : std::false_type
+ template<typename _Alloc>
+ struct hash<basic_string<char16_t, char_traits<char16_t>, _Alloc>>
+ : public __str_hash_base<char16_t, _Alloc>
{ };
/// std::hash specialization for u32string.
- template<>
- struct hash<u32string>
- : public __hash_base<size_t, u32string>
- {
- size_t
- operator()(const u32string& __s) const noexcept
- { return std::_Hash_impl::hash(__s.data(),
- __s.length() * sizeof(char32_t)); }
- };
-
- template<>
- struct __is_fast_hash<hash<u32string>> : std::false_type
+ template<typename _Alloc>
+ struct hash<basic_string<char32_t, char_traits<char32_t>, _Alloc>>
+ : public __str_hash_base<char32_t, _Alloc>
{ };
+#if ! _GLIBCXX_INLINE_VERSION
+ // PR libstdc++/105907 - __is_fast_hash affects unordered container ABI.
+ template<> struct __is_fast_hash<hash<string>> : std::false_type { };
+ template<> struct __is_fast_hash<hash<wstring>> : std::false_type { };
+ template<> struct __is_fast_hash<hash<u16string>> : std::false_type { };
+ template<> struct __is_fast_hash<hash<u32string>> : std::false_type { };
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<> struct __is_fast_hash<hash<u8string>> : std::false_type { };
+#endif
+#else
+ // For versioned namespace, assume every std::hash<basic_string<>> is slow.
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ struct __is_fast_hash<hash<basic_string<_CharT, _Traits, _Alloc>>>
+ : std::false_type
+ { };
+#endif
+
#if __cplusplus >= 201402L
#define __cpp_lib_string_udls 201304L
@@ -69,39 +69,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using u32string = basic_string<char32_t>;
using wstring = basic_string<wchar_t>;
} // namespace pmr
-
- template<typename _Str>
- struct __hash_string_base
- : public __hash_base<size_t, _Str>
- {
- size_t
- operator()(const _Str& __s) const noexcept
- { return hash<basic_string_view<typename _Str::value_type>>{}(__s); }
- };
-
- template<>
- struct hash<pmr::string>
- : public __hash_string_base<pmr::string>
- { };
-#ifdef _GLIBCXX_USE_CHAR8_T
- template<>
- struct hash<pmr::u8string>
- : public __hash_string_base<pmr::u8string>
- { };
-#endif
- template<>
- struct hash<pmr::u16string>
- : public __hash_string_base<pmr::u16string>
- { };
- template<>
- struct hash<pmr::u32string>
- : public __hash_string_base<pmr::u32string>
- { };
- template<>
- struct hash<pmr::wstring>
- : public __hash_string_base<pmr::wstring>
- { };
-
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
@@ -20,6 +20,7 @@
#include <string>
#include <memory_resource>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
// C++17 24.3.5 [basic.string.hash]
// If S is one of these string types, SV is the corresponding string view type,
@@ -54,9 +55,24 @@ test02()
#endif
}
+template<typename C>
+using String
+ = std::basic_string<C, std::char_traits<C>, __gnu_test::SimpleAllocator<C>>;
+
+void
+test03()
+{
+ // LWG 3705. Hashability shouldn't depend on basic_string's allocator
+ VERIFY( test(String<char>("a narrow string")) );
+ VERIFY( test(String<char16_t>(u"a utf-16 string")) );
+ VERIFY( test(String<char32_t>(U"a utf-32 string")) );
+ VERIFY( test(String<wchar_t>(L"a wide string")) );
+}
+
int
main()
{
test01();
test02();
+ test03();
}
@@ -21,6 +21,7 @@
#include <string>
#include <memory_resource>
#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
// C++2a N4810 21.3.5 [basic.string.hash]
// If S is one of these string types, SV is the corresponding string view type,
@@ -55,9 +56,20 @@ test02()
VERIFY( hash<std::string>()(native) == hash<std::u8string>()(utf8) );
}
+void
+test03()
+{
+ using Alloc = __gnu_test::SimpleAllocator<char8_t>;
+ using Stringu8 = std::basic_string<char8_t, std::char_traits<char8_t>, Alloc>;
+
+ // LWG 3705. Hashability shouldn't depend on basic_string's allocator
+ VERIFY( test(Stringu8(u8"a utf-8 string, with custom allocator")) );
+}
+
int
main()
{
test01();
test02();
+ test03();
}