diff options
-rw-r--r-- | libstdc++-v3/include/bits/basic_string.h | 102 | ||||
-rw-r--r-- | libstdc++-v3/include/std/string | 33 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc | 16 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc | 12 |
4 files changed, 74 insertions, 89 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 6041d05..f76ddf9 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -4226,85 +4226,75 @@ 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 -#ifndef _GLIBCXX_COMPATIBILITY_CXX0X - /// std::hash specialization for string. - template<> - struct hash<string> - : public __hash_base<size_t, string> + 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 string& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), __s.length()); } + operator()(const _StrT& __s) const noexcept + { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); } }; - template<> - struct __is_fast_hash<hash<string>> : std::false_type +#ifndef _GLIBCXX_COMPATIBILITY_CXX0X + /// std::hash specialization for string. + 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<typename _Alloc> + struct hash<basic_string<char32_t, char_traits<char32_t>, _Alloc>> + : public __str_hash_base<char32_t, _Alloc> + { }; - template<> - struct __is_fast_hash<hash<u32string>> : std::false_type +#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 diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 4a06330..37a4aab 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -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 diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc index 4c16f0e..7f38099 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc @@ -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(); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc index 217fe15..0ff98ad 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc @@ -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(); } |