[libc++] Implement LWG3657 std::hash<filesystem::path>
authorLouis Dionne <ldionne.2@gmail.com>
Tue, 7 Feb 2023 01:35:42 +0000 (17:35 -0800)
committerLouis Dionne <ldionne.2@gmail.com>
Wed, 8 Feb 2023 06:06:17 +0000 (22:06 -0800)
This is implemented as a DR on top of C++17.

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

libcxx/docs/Status/Cxx2bIssues.csv
libcxx/include/__filesystem/path.h
libcxx/include/filesystem
libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash.tested_elswhere.compile.pass.cpp [new file with mode: 0644]
libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash_value.tested_elswhere.compile.pass.cpp [moved from libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp with 67% similarity]

index cac68bc..dbcdcb3 100644 (file)
 "`3649 <https://wg21.link/LWG3649>`__","[fund.ts.v2] Reinstate and bump ``__cpp_lib_experimental_memory_resource`` feature test macro","February 2022","",""
 "`3650 <https://wg21.link/LWG3650>`__","Are ``std::basic_string`` 's ``iterator`` and ``const_iterator`` constexpr iterators?","February 2022","|Nothing to do|",""
 "`3654 <https://wg21.link/LWG3654>`__","``basic_format_context::arg(size_t)`` should be ``noexcept`` ","February 2022","|Complete|","15.0","|format|"
-"`3657 <https://wg21.link/LWG3657>`__","``std::hash<std::filesystem::path>`` is not enabled","February 2022","",""
+"`3657 <https://wg21.link/LWG3657>`__","``std::hash<std::filesystem::path>`` is not enabled","February 2022","|Complete|","17.0"
 "`3660 <https://wg21.link/LWG3660>`__","``iterator_traits<common_iterator>::pointer`` should conform to ยง[iterator.traits]","February 2022","|Complete|","14.0","|ranges|"
 "`3661 <https://wg21.link/LWG3661>`__","``constinit atomic<shared_ptr<T>> a(nullptr);`` should work","February 2022","",""
 "","","","","",""
index 4e6912f..aad0beb 100644 (file)
@@ -14,6 +14,8 @@
 #include <__algorithm/replace_copy.h>
 #include <__availability>
 #include <__config>
+#include <__functional/unary_function.h>
+#include <__fwd/hash.h>
 #include <__iterator/back_insert_iterator.h>
 #include <__iterator/iterator_traits.h>
 #include <cstddef>
@@ -1086,6 +1088,17 @@ _LIBCPP_AVAILABILITY_FILESYSTEM_POP
 
 _LIBCPP_END_NAMESPACE_FILESYSTEM
 
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <>
+struct _LIBCPP_AVAILABILITY_FILESYSTEM hash<_VSTD_FS::path> : __unary_function<_VSTD_FS::path, size_t> {
+  _LIBCPP_HIDE_FROM_ABI size_t operator()(_VSTD_FS::path const& __p) const noexcept {
+    return _VSTD_FS::hash_value(__p);
+  }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
 #endif // _LIBCPP_CXX03_LANG
 
 #endif // _LIBCPP___FILESYSTEM_PATH_H
index 7efa4ed..8d01a81 100644 (file)
     void swap(path& lhs, path& rhs) noexcept;
     size_t hash_value(const path& p) noexcept;
 
+    // [fs.path.hash], hash support
+    template<> struct hash<filesystem::path>;
+
     template <class Source>
       path u8path(const Source& source);
     template <class InputIterator>
index 3e194a7..365aa1c 100644 (file)
@@ -134,6 +134,14 @@ void test_compare_basic()
       ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1)));
       ASSERT_NOEXCEPT(hash_value(p1));
     }
+    { // check std::hash
+      auto h1 = std::hash<fs::path>()(p1);
+      auto h2 = std::hash<fs::path>()(p2);
+      assert((h1 == h2) == (p1 == p2));
+      // check signature
+      ASSERT_SAME_TYPE(size_t, decltype(std::hash<fs::path>()(p1)));
+      ASSERT_NOEXCEPT(std::hash<fs::path>()(p1));
+    }
   }
 }
 
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash.tested_elswhere.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash.tested_elswhere.compile.pass.cpp
new file mode 100644 (file)
index 0000000..b69e224
--- /dev/null
@@ -0,0 +1,10 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// The std::hash specialization is tested as part of [path.compare]
+// in libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
@@ -6,10 +6,5 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
-
-// The "hash_value" function is tested as part of [path.compare]
-// in class.path/path.members/path.compare.pass.cpp
-int main(int, char**) {
-  return 0;
-}
+// The `hash_value` function is tested as part of [path.compare]
+// in libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp