Skip to content

Commit 1cf344d

Browse files
committed
[libc++] Implement LWG3657 std::hash<filesystem::path>
This is implemented as a DR on top of C++17. Differential Revision: https://reviews.llvm.org/D143452
1 parent 7bc2cd6 commit 1cf344d

File tree

6 files changed

+37
-8
lines changed

6 files changed

+37
-8
lines changed

libcxx/docs/Status/Cxx2bIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
"`3649 <https://wg21.link/LWG3649>`__","[fund.ts.v2] Reinstate and bump ``__cpp_lib_experimental_memory_resource`` feature test macro","February 2022","",""
156156
"`3650 <https://wg21.link/LWG3650>`__","Are ``std::basic_string`` 's ``iterator`` and ``const_iterator`` constexpr iterators?","February 2022","|Nothing to do|",""
157157
"`3654 <https://wg21.link/LWG3654>`__","``basic_format_context::arg(size_t)`` should be ``noexcept`` ","February 2022","|Complete|","15.0","|format|"
158-
"`3657 <https://wg21.link/LWG3657>`__","``std::hash<std::filesystem::path>`` is not enabled","February 2022","",""
158+
"`3657 <https://wg21.link/LWG3657>`__","``std::hash<std::filesystem::path>`` is not enabled","February 2022","|Complete|","17.0"
159159
"`3660 <https://wg21.link/LWG3660>`__","``iterator_traits<common_iterator>::pointer`` should conform to §[iterator.traits]","February 2022","|Complete|","14.0","|ranges|"
160160
"`3661 <https://wg21.link/LWG3661>`__","``constinit atomic<shared_ptr<T>> a(nullptr);`` should work","February 2022","",""
161161
"","","","","",""

libcxx/include/__filesystem/path.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <__algorithm/replace_copy.h>
1515
#include <__availability>
1616
#include <__config>
17+
#include <__functional/unary_function.h>
18+
#include <__fwd/hash.h>
1719
#include <__iterator/back_insert_iterator.h>
1820
#include <__iterator/iterator_traits.h>
1921
#include <cstddef>
@@ -1086,6 +1088,17 @@ _LIBCPP_AVAILABILITY_FILESYSTEM_POP
10861088

10871089
_LIBCPP_END_NAMESPACE_FILESYSTEM
10881090

1091+
_LIBCPP_BEGIN_NAMESPACE_STD
1092+
1093+
template <>
1094+
struct _LIBCPP_AVAILABILITY_FILESYSTEM hash<_VSTD_FS::path> : __unary_function<_VSTD_FS::path, size_t> {
1095+
_LIBCPP_HIDE_FROM_ABI size_t operator()(_VSTD_FS::path const& __p) const noexcept {
1096+
return _VSTD_FS::hash_value(__p);
1097+
}
1098+
};
1099+
1100+
_LIBCPP_END_NAMESPACE_STD
1101+
10891102
#endif // _LIBCPP_CXX03_LANG
10901103

10911104
#endif // _LIBCPP___FILESYSTEM_PATH_H

libcxx/include/filesystem

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@
159159
void swap(path& lhs, path& rhs) noexcept;
160160
size_t hash_value(const path& p) noexcept;
161161
162+
// [fs.path.hash], hash support
163+
template<> struct hash<filesystem::path>;
164+
162165
template <class Source>
163166
path u8path(const Source& source);
164167
template <class InputIterator>

libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ void test_compare_basic()
134134
ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1)));
135135
ASSERT_NOEXCEPT(hash_value(p1));
136136
}
137+
{ // check std::hash
138+
auto h1 = std::hash<fs::path>()(p1);
139+
auto h2 = std::hash<fs::path>()(p2);
140+
assert((h1 == h2) == (p1 == p2));
141+
// check signature
142+
ASSERT_SAME_TYPE(size_t, decltype(std::hash<fs::path>()(p1)));
143+
ASSERT_NOEXCEPT(std::hash<fs::path>()(p1));
144+
}
137145
}
138146
}
139147

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// The std::hash specialization is tested as part of [path.compare]
10+
// in 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_value_tested_elswhere.pass.cpp renamed to libcxx/test/std/input.output/filesystems/class.path/path.nonmember/hash_value.tested_elswhere.compile.pass.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,5 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
// UNSUPPORTED: c++03
10-
11-
// The "hash_value" function is tested as part of [path.compare]
12-
// in class.path/path.members/path.compare.pass.cpp
13-
int main(int, char**) {
14-
return 0;
15-
}
9+
// The `hash_value` function is tested as part of [path.compare]
10+
// in libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp

0 commit comments

Comments
 (0)