[libc++] Enable hash only for the correct types
authorNikolas Klauser <nikolasklauser@berlin.de>
Mon, 22 Aug 2022 00:59:09 +0000 (02:59 +0200)
committerNikolas Klauser <nikolasklauser@berlin.de>
Fri, 26 Aug 2022 15:40:23 +0000 (17:40 +0200)
Also implement LWG3705.
Fixes https://github.com/llvm/llvm-project/issues/55823

Reviewed By: ldionne, #libc

Spies: libcxx-commits

Differential Revision: https://reviews.llvm.org/D132338

libcxx/docs/Status/Cxx2bIssues.csv
libcxx/include/string
libcxx/include/string_view
libcxx/test/std/strings/basic.string.hash/enabled_hashes.pass.cpp
libcxx/test/std/strings/string.view/string.view.hash/enabled_hashes.pass.cpp

index ab3c680..0541ef2 100644 (file)
 "`3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","",""
 "`3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","July 2022","",""
 "`3704 <https://wg21.link/LWG3704>`__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","",""
-"`3705 <https://wg21.link/LWG3705>`__","Hashability shouldn't depend on basic_string's allocator","July 2022","",""
+"`3705 <https://wg21.link/LWG3705>`__","Hashability shouldn't depend on basic_string's allocator","July 2022","|Complete|","16.0"
 "`3707 <https://wg21.link/LWG3707>`__","chunk_view::outer-iterator::value_type::size should return unsigned type","July 2022","","","|ranges|"
 "`3708 <https://wg21.link/LWG3708>`__","``take_while_view::sentinel``'s conversion constructor should move","July 2022","","","|ranges|"
 "`3709 <https://wg21.link/LWG3709>`__","LWG-3703 was underly ambitious","July 2022","",""
index 07bf333..2180f86 100644 (file)
@@ -4597,15 +4597,32 @@ const typename basic_string<_CharT, _Traits, _Allocator>::size_type
                basic_string<_CharT, _Traits, _Allocator>::npos;
 
 template <class _CharT, class _Allocator>
-struct _LIBCPP_TEMPLATE_VIS
-    hash<basic_string<_CharT, char_traits<_CharT>, _Allocator> >
-    : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t>
+struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t>
 {
     size_t
     operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT
     { return __do_string_hash(__val.data(), __val.data() + __val.size()); }
 };
 
+template <class _Allocator>
+struct hash<basic_string<char, char_traits<char>, _Allocator> > : __string_hash<char, _Allocator> {};
+
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+template <class _Allocator>
+struct hash<basic_string<char8_t, char_traits<char8_t>, _Allocator> > : __string_hash<char8_t, _Allocator> {};
+#endif
+
+template <class _Allocator>
+struct hash<basic_string<char16_t, char_traits<char16_t>, _Allocator> > : __string_hash<char16_t, _Allocator> {};
+
+template <class _Allocator>
+struct hash<basic_string<char32_t, char_traits<char32_t>, _Allocator> > : __string_hash<char32_t, _Allocator> {};
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <class _Allocator>
+struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Allocator> > : __string_hash<wchar_t, _Allocator> {};
+#endif
+
 template<class _CharT, class _Traits, class _Allocator>
 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
 operator<<(basic_ostream<_CharT, _Traits>& __os,
index f15531e..d0c70a2 100644 (file)
@@ -962,8 +962,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os,
 
 // [string.view.hash]
 template<class _CharT>
-struct _LIBCPP_TEMPLATE_VIS hash<basic_string_view<_CharT, char_traits<_CharT> > >
-    : public __unary_function<basic_string_view<_CharT, char_traits<_CharT> >, size_t>
+struct __string_view_hash : public __unary_function<basic_string_view<_CharT, char_traits<_CharT> >, size_t>
 {
     _LIBCPP_INLINE_VISIBILITY
     size_t operator()(const basic_string_view<_CharT, char_traits<_CharT> > __val) const _NOEXCEPT {
@@ -971,6 +970,25 @@ struct _LIBCPP_TEMPLATE_VIS hash<basic_string_view<_CharT, char_traits<_CharT> >
     }
 };
 
+template <>
+struct hash<basic_string_view<char, char_traits<char> > > : __string_view_hash<char> {};
+
+#ifndef _LIBCPP_HAS_NO_CHAR8_T
+template <>
+struct hash<basic_string_view<char8_t, char_traits<char8_t> > > : __string_view_hash<char8_t> {};
+#endif
+
+template <>
+struct hash<basic_string_view<char16_t, char_traits<char16_t> > > : __string_view_hash<char16_t> {};
+
+template <>
+struct hash<basic_string_view<char32_t, char_traits<char32_t> > > : __string_view_hash<char32_t> {};
+
+#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template <>
+struct hash<basic_string_view<wchar_t, char_traits<wchar_t> > > : __string_view_hash<wchar_t> {};
+#endif
+
 #if _LIBCPP_STD_VER > 11
 inline namespace literals
 {
index 7e620b3..f827358 100644 (file)
 
 #include <string>
 
+#include "constexpr_char_traits.h"
 #include "poisoned_hash_helper.h"
-
+#include "test_allocator.h"
 #include "test_macros.h"
 
+struct MyChar {
+  char c;
+};
+
 int main(int, char**) {
   test_library_hash_specializations_available();
   {
@@ -31,6 +36,9 @@ int main(int, char**) {
 #endif
     test_hash_enabled_for_type<std::u16string>();
     test_hash_enabled_for_type<std::u32string>();
+    test_hash_enabled_for_type<std::basic_string<char, std::char_traits<char>, test_allocator<char>>>();
+    test_hash_disabled_for_type<std::basic_string<MyChar, std::char_traits<MyChar>, std::allocator<MyChar>>>();
+    test_hash_disabled_for_type<std::basic_string<char, constexpr_char_traits<char>, std::allocator<char>>>();
   }
 
   return 0;
index 5bea72e..c214ac1 100644 (file)
 
 #include <string_view>
 
+#include "constexpr_char_traits.h"
 #include "poisoned_hash_helper.h"
-
 #include "test_macros.h"
 
+struct MyChar {
+  char c;
+};
+
 int main(int, char**) {
   test_library_hash_specializations_available();
   {
@@ -32,6 +36,8 @@ int main(int, char**) {
 #endif
     test_hash_enabled_for_type<std::u16string_view>();
     test_hash_enabled_for_type<std::u32string_view>();
+    test_hash_disabled_for_type<std::basic_string_view<MyChar, std::char_traits<MyChar>>>();
+    test_hash_disabled_for_type<std::basic_string_view<char, constexpr_char_traits<char>>>();
   }
 
   return 0;