Define std::hash specializations for C++17 PMR strings
authorJonathan Wakely <jwakely@redhat.com>
Wed, 3 Apr 2019 09:47:47 +0000 (10:47 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 3 Apr 2019 09:47:47 +0000 (10:47 +0100)
These hash specializations should have been added when the pmr::string
and related typedefs were added.

* include/std/string (__hash_string_base): New class template defining
operator() for hashing strings.
(hash<pmr::string>, hash<pmr::u8string>, hash<pmr::u16string>)
(hash<pmr::u32string>, hash<pmr::wstring>): Define for C++17.
* testsuite/21_strings/basic_string/hash/hash.cc: New test.
* testsuite/21_strings/basic_string/hash/hash_char8_t.cc: New test.

From-SVN: r270116

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/string
libstdc++-v3/testsuite/21_strings/basic_string/hash/hash.cc [new file with mode: 0644]
libstdc++-v3/testsuite/21_strings/basic_string/hash/hash_char8_t.cc [new file with mode: 0644]

index 0b3d0c2d7e807afacd7e9cddb551fdebc9ef505f..422ec850a5dd0ea3d74959f8bf2c4c3de725e6f5 100644 (file)
@@ -1,3 +1,12 @@
+2019-04-03  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/std/string (__hash_string_base): New class template defining
+       operator() for hashing strings.
+       (hash<pmr::string>, hash<pmr::u8string>, hash<pmr::u16string>)
+       (hash<pmr::u32string>, hash<pmr::wstring>): Define for C++17.
+       * testsuite/21_strings/basic_string/hash/hash.cc: New test.
+       * testsuite/21_strings/basic_string/hash/hash_char8_t.cc: New test.
+
 2019-04-01  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        Use single-visitation in variant assignment and swap and relops.
index 100c6c84ef604670ffc5b18958125523a4de37d8..6ccc06f337aabb253978ee964891330e6dac848d 100644 (file)
@@ -74,6 +74,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using wstring   = basic_string<wchar_t>;
 #endif
   } // 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>
+    { };
+#ifdef _GLIBCXX_USE_WCHAR_T
+  template<>
+    struct hash<pmr::wstring>
+    : public __hash_string_base<pmr::wstring>
+    { };
+#endif
+
 _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
new file mode 100644 (file)
index 0000000..9bdf9bd
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target c++17 } }
+
+#include <string>
+#include <memory_resource>
+#include <testsuite_hooks.h>
+
+// C++17 24.3.5 [basic.string.hash]
+// If S is one of these string types, SV is the corresponding string view type,
+// and s is an object of type S, then hash<S>()(s) == hash<SV>()(SV(s)).
+
+template<typename S>
+  bool
+  test(const S& s)
+  {
+    using std::hash;
+    using SV = std::basic_string_view<typename S::value_type>;
+    return hash<S>()(s) == hash<SV>()(SV(s));
+  }
+
+void
+test01()
+{
+  VERIFY( test(std::string("a narrow string")) );
+  VERIFY( test(std::pmr::string("a narrow string, but with PMR!")) );
+  VERIFY( test(std::u16string(u"a utf-16 string")) );
+  VERIFY( test(std::pmr::u16string(u"a utf-16 string, but with PMR!")) );
+  VERIFY( test(std::u32string(U"a utf-32 string")) );
+  VERIFY( test(std::pmr::u32string(U"a utf-32 string, but with PMR!")) );
+#if _GLIBCXX_USE_WCHAR_T
+  VERIFY( test(std::wstring(L"a wide string")) );
+  VERIFY( test(std::pmr::wstring(L"a wide string, but with PMR!")) );
+#endif
+}
+
+int
+main()
+{
+  test01();
+}
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
new file mode 100644 (file)
index 0000000..0e4cfae
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <string>
+#include <memory_resource>
+#include <testsuite_hooks.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,
+// and s is an object of type S, then hash<S>()(s) == hash<SV>()(SV(s)).
+
+template<typename S>
+  bool
+  test(const S& s)
+  {
+    using std::hash;
+    using SV = std::basic_string_view<typename S::value_type>;
+    return hash<S>()(s) == hash<SV>()(SV(s));
+  }
+
+void
+test01()
+{
+  VERIFY( test(std::string("a narrow string")) );
+  VERIFY( test(std::pmr::string("a narrow string, but with PMR!")) );
+  VERIFY( test(std::u8string(u8"a utf-8 string")) );
+  VERIFY( test(std::pmr::u8string(u8"a utf-8 string, but with PMR!")) );
+}
+
+void
+test02()
+{
+  using std::hash;
+  std::string native("a string, a string, my stringdom for a string");
+  std::u8string utf8(u8"a string, a string, my stringdom for a string");
+  VERIFY( hash<std::string>()(native) == hash<std::u8string>()(utf8) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}