From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id D394E3889A7B for ; Fri, 10 Jun 2022 14:10:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D394E3889A7B Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-336-nhVn_PcgNVa4fByFkuVKEw-1; Fri, 10 Jun 2022 10:09:59 -0400 X-MC-Unique: nhVn_PcgNVa4fByFkuVKEw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1ADE21C05AE1; Fri, 10 Jun 2022 14:09:59 +0000 (UTC) Received: from localhost (unknown [10.33.36.159]) by smtp.corp.redhat.com (Postfix) with ESMTP id D4A9E40D2827; Fri, 10 Jun 2022 14:09:58 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Make std::hash> allocator-agnostic (LWG 3705) Date: Fri, 10 Jun 2022 15:09:58 +0100 Message-Id: <20220610140958.659996-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jun 2022 14:10:04 -0000 Tested powerpc64le-linux, pushed to trunk. -- >8 -- This new library issue was recently moved to Tentatively Ready by an LWG poll, so I'm making the change on trunk. As noted in PR libstc++/105907 the std::hash specializations for PMR strings were not treated as slow hashes by the unordered containers, so this change preserves that. The new specializations for custom allocators are also not treated as slow, for the same reason. For the versioned namespace (i.e. unstable ABI) we don't have to worry about that, so can enable hash code caching for all basic_string specializations. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (__hash_str_base): New class template. (hash, A>>): Define partial specialization for each of the standard character types. (hash, hash, hash, hash) (hash): Remove explicit specializations. * include/std/string (__hash_string_base): Remove class template. (hash, hash, hash) (hash, hash): Remove explicit specializations. * testsuite/21_strings/basic_string/hash/hash.cc: Test with custom allocators. * testsuite/21_strings/basic_string/hash/hash_char8_t.cc: Likewise. --- libstdc++-v3/include/bits/basic_string.h | 108 ++++++++---------- libstdc++-v3/include/std/string | 33 ------ .../21_strings/basic_string/hash/hash.cc | 16 +++ .../basic_string/hash/hash_char8_t.cc | 12 ++ 4 files changed, 77 insertions(+), 92 deletions(-) diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 6041d05815b..f76ddf970c6 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -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, _Alloc>> + struct __str_hash_base + : public __hash_base + { + 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 - : public __hash_base - { - size_t - operator()(const string& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), __s.length()); } - }; - - template<> - struct __is_fast_hash> : std::false_type + template + struct hash, _Alloc>> + : public __str_hash_base { }; /// std::hash specialization for wstring. - template<> - struct hash - : public __hash_base - { - size_t - operator()(const wstring& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), - __s.length() * sizeof(wchar_t)); } - }; + template + struct hash, _Alloc>> + : public __str_hash_base + { }; - template<> - struct __is_fast_hash> : std::false_type + template + struct __is_fast_hash, + _Alloc>>> + : std::false_type { }; #endif /* _GLIBCXX_COMPATIBILITY_CXX0X */ #ifdef _GLIBCXX_USE_CHAR8_T /// std::hash specialization for u8string. - template<> - struct hash - : public __hash_base - { - 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> : std::false_type + template + struct hash, _Alloc>> + : public __str_hash_base { }; #endif /// std::hash specialization for u16string. - template<> - struct hash - : public __hash_base - { - 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> : std::false_type + template + struct hash, _Alloc>> + : public __str_hash_base { }; /// std::hash specialization for u32string. - template<> - struct hash - : public __hash_base - { - 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> : std::false_type + template + struct hash, _Alloc>> + : public __str_hash_base { }; +#if ! _GLIBCXX_INLINE_VERSION + // PR libstdc++/105907 - __is_fast_hash affects unordered container ABI. + template<> struct __is_fast_hash> : std::false_type { }; + template<> struct __is_fast_hash> : std::false_type { }; + template<> struct __is_fast_hash> : std::false_type { }; + template<> struct __is_fast_hash> : std::false_type { }; +#ifdef _GLIBCXX_USE_CHAR8_T + template<> struct __is_fast_hash> : std::false_type { }; +#endif +#else + // For versioned namespace, assume every std::hash> is slow. + template + struct __is_fast_hash>> + : std::false_type + { }; +#endif + #if __cplusplus >= 201402L #define __cpp_lib_string_udls 201304L diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 4a0633067bd..37a4aaba9cd 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; using wstring = basic_string; } // namespace pmr - - template - struct __hash_string_base - : public __hash_base - { - size_t - operator()(const _Str& __s) const noexcept - { return hash>{}(__s); } - }; - - template<> - struct hash - : public __hash_string_base - { }; -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct hash - : public __hash_string_base - { }; -#endif - template<> - struct hash - : public __hash_string_base - { }; - template<> - struct hash - : public __hash_string_base - { }; - template<> - struct hash - : public __hash_string_base - { }; - _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 4c16f0e6f40..7f3809926e5 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 #include #include +#include // 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 +using String + = std::basic_string, __gnu_test::SimpleAllocator>; + +void +test03() +{ + // LWG 3705. Hashability shouldn't depend on basic_string's allocator + VERIFY( test(String("a narrow string")) ); + VERIFY( test(String(u"a utf-16 string")) ); + VERIFY( test(String(U"a utf-32 string")) ); + VERIFY( test(String(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 217fe15c7fe..0ff98ad1caa 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 #include #include +#include // 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()(native) == hash()(utf8) ); } +void +test03() +{ + using Alloc = __gnu_test::SimpleAllocator; + using Stringu8 = std::basic_string, 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(); } -- 2.34.3