[libcxx-commits] [libcxx] f1974f0 - [libc++] Implement `operator<=>` for `filesystem::directory_entry`
Adrian Vogelsgesang via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 18 14:46:25 PDT 2022
Author: Adrian Vogelsgesang
Date: 2022-08-18T14:46:13-07:00
New Revision: f1974f039fa76316721a2228b3241f17489f6f7b
URL: https://github.com/llvm/llvm-project/commit/f1974f039fa76316721a2228b3241f17489f6f7b
DIFF: https://github.com/llvm/llvm-project/commit/f1974f039fa76316721a2228b3241f17489f6f7b.diff
LOG: [libc++] Implement `operator<=>` for `filesystem::directory_entry`
Implements part of P1614R2 "The Mothership has Landed"
Differential Revision: https://reviews.llvm.org/D130860
Added:
Modified:
libcxx/docs/Status/SpaceshipProjects.csv
libcxx/include/__filesystem/directory_entry.h
libcxx/include/filesystem
libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 6f3ea312e99b7..9a88dfdd1f9e4 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -76,6 +76,6 @@ Section,Description,Dependencies,Assignee,Complete
| chrono::time_zone_link",A ``<chrono>`` implementation,Unassigned,|Not Started|
| `[fs.filesystem.syn] <https://wg21.link/fs.filesystem.syn>`_,| `filesystem::space_info <https://reviews.llvm.org/D130861>`_,None,Adrian Vogelsgesang,|Complete|
| `[fs.path.nonmember] <https://wg21.link/fs.path.nonmember>`_,| `filesystem::path <https://reviews.llvm.org/D130859>`_,None,Adrian Vogelsgesang,|Complete|
-| `[fs.dir.entry.obs] <https://wg21.link/fs.dir.entry.obs>`_,| `filesystem::directory_entry <https://reviews.llvm.org/D130860>`_,None,Adrian Vogelsgesang,|In Progress|
+| `[fs.dir.entry.obs] <https://wg21.link/fs.dir.entry.obs>`_,| `filesystem::directory_entry <https://reviews.llvm.org/D130860>`_,None,Adrian Vogelsgesang,|Complete|
| `[re.submatch.op] <https://wg21.link/re.submatch.op>`_,| sub_match,None,Mark de Wever,|In Progress|
| `[thread.thread.id] <https://wg21.link/thread.thread.id>`_,| `thread::id <https://reviews.llvm.org/D131362>`_,None,Adrian Vogelsgesang,|Complete|
diff --git a/libcxx/include/__filesystem/directory_entry.h b/libcxx/include/__filesystem/directory_entry.h
index 5ba3ef96de481..b17eaaab4c545 100644
--- a/libcxx/include/__filesystem/directory_entry.h
+++ b/libcxx/include/__filesystem/directory_entry.h
@@ -215,21 +215,23 @@ class directory_entry {
return __get_symlink_status(&__ec);
}
- _LIBCPP_INLINE_VISIBILITY
- bool operator<(directory_entry const& __rhs) const noexcept {
- return __p_ < __rhs.__p_;
- }
_LIBCPP_INLINE_VISIBILITY
bool operator==(directory_entry const& __rhs) const noexcept {
return __p_ == __rhs.__p_;
}
+#if _LIBCPP_STD_VER <= 17
_LIBCPP_INLINE_VISIBILITY
bool operator!=(directory_entry const& __rhs) const noexcept {
return __p_ != __rhs.__p_;
}
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator<(directory_entry const& __rhs) const noexcept {
+ return __p_ < __rhs.__p_;
+ }
+
_LIBCPP_INLINE_VISIBILITY
bool operator<=(directory_entry const& __rhs) const noexcept {
return __p_ <= __rhs.__p_;
@@ -245,6 +247,15 @@ class directory_entry {
return __p_ >= __rhs.__p_;
}
+#else // _LIBCPP_STD_VER <= 17
+
+ _LIBCPP_HIDE_FROM_ABI
+ strong_ordering operator<=>(const directory_entry& __rhs) const noexcept {
+ return __p_ <=> __rhs.__p_;
+ }
+
+#endif // _LIBCPP_STD_VER <= 17
+
template <class _CharT, class _Traits>
_LIBCPP_INLINE_VISIBILITY
friend basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const directory_entry& __d) {
diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem
index 8b81e10515a6e..086d59764f489 100644
--- a/libcxx/include/filesystem
+++ b/libcxx/include/filesystem
@@ -164,7 +164,73 @@
path u8path(InputIterator first, InputIterator last);
class filesystem_error;
- class directory_entry;
+
+ class directory_entry {
+ public:
+ directory_entry() noexcept = default;
+ directory_entry(const directory_entry&) = default;
+ directory_entry(directory_entry&&) noexcept = default;
+ explicit directory_entry(const filesystem::path& p);
+ directory_entry(const filesystem::path& p, error_code& ec);
+ ~directory_entry();
+
+ directory_entry& operator=(const directory_entry&) = default;
+ directory_entry& operator=(directory_entry&&) noexcept = default;
+
+ void assign(const filesystem::path& p);
+ void assign(const filesystem::path& p, error_code& ec);
+ void replace_filename(const filesystem::path& p);
+ void replace_filename(const filesystem::path& p, error_code& ec);
+ void refresh();
+ void refresh(error_code& ec) noexcept;
+
+ const filesystem::path& path() const noexcept;
+ operator const filesystem::path&() const noexcept;
+ bool exists() const;
+ bool exists(error_code& ec) const noexcept;
+ bool is_block_file() const;
+ bool is_block_file(error_code& ec) const noexcept;
+ bool is_character_file() const;
+ bool is_character_file(error_code& ec) const noexcept;
+ bool is_directory() const;
+ bool is_directory(error_code& ec) const noexcept;
+ bool is_fifo() const;
+ bool is_fifo(error_code& ec) const noexcept;
+ bool is_other() const;
+ bool is_other(error_code& ec) const noexcept;
+ bool is_regular_file() const;
+ bool is_regular_file(error_code& ec) const noexcept;
+ bool is_socket() const;
+ bool is_socket(error_code& ec) const noexcept;
+ bool is_symlink() const;
+ bool is_symlink(error_code& ec) const noexcept;
+ uintmax_t file_size() const;
+ uintmax_t file_size(error_code& ec) const noexcept;
+ uintmax_t hard_link_count() const;
+ uintmax_t hard_link_count(error_code& ec) const noexcept;
+ file_time_type last_write_time() const;
+ file_time_type last_write_time(error_code& ec) const noexcept;
+ file_status status() const;
+ file_status status(error_code& ec) const noexcept;
+ file_status symlink_status() const;
+ file_status symlink_status(error_code& ec) const noexcept;
+
+ bool operator==(const directory_entry& rhs) const noexcept;
+ bool operator!=(const directory_entry& rhs) const noexcept; // removed in C++20
+ bool operator< (const directory_entry& rhs) const noexcept; // removed in C++20
+ bool operator<=(const directory_entry& rhs) const noexcept; // removed in C++20
+ bool operator> (const directory_entry& rhs) const noexcept; // removed in C++20
+ bool operator>=(const directory_entry& rhs) const noexcept; // removed in C++20
+ strong_ordering operator<=>(const directory_entry& rhs) const noexcept; // since C++20
+
+ template<class charT, class traits>
+ friend basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
+
+ private:
+ filesystem::path pathobject; // exposition only
+ friend class directory_iterator; // exposition only
+ };
class directory_iterator;
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp
index f7e5770a7cd73..6683ac157ec10 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp
@@ -18,6 +18,7 @@
// bool operator<=(directory_entry const&) const noexcept;
// bool operator> (directory_entry const&) const noexcept;
// bool operator>=(directory_entry const&) const noexcept;
+// strong_ordering operator<=>(directory_entry const&) const noexcept;
#include "filesystem_include.h"
#include <cassert>
@@ -25,61 +26,28 @@
#include <utility>
#include "test_macros.h"
+#include "test_comparisons.h"
-
-#define CHECK_OP(Op) \
- static_assert(std::is_same<decltype(ce Op ce), bool>::value, ""); \
- static_assert(noexcept(ce Op ce), "Operation must be noexcept" )
-
-void test_comparison_signatures() {
+int main(int, char**) {
using namespace fs;
- path const p("foo/bar/baz");
- // Check that the operators are valid, yield bool, and are not
- // potentially-throwing.
- {
- directory_entry const ce(p);
- CHECK_OP(==);
- CHECK_OP(!=);
- CHECK_OP(< );
- CHECK_OP(<=);
- CHECK_OP(> );
- CHECK_OP(>=);
- }
-}
-#undef CHECK_OP
-// The actual semantics of the comparisons are testing via paths operators.
-void test_comparisons_simple() {
- using namespace fs;
+ AssertComparisonsAreNoexcept<directory_entry>();
+ AssertComparisonsReturnBool<directory_entry>();
+#if TEST_STD_VER > 17
+ AssertOrderAreNoexcept<directory_entry>();
+ AssertOrderReturn<std::strong_ordering, directory_entry>();
+#endif
+
typedef std::pair<path, path> TestType;
- TestType TestCases[] =
- {
- {"", ""},
- {"", "a"},
- {"a", "a"},
- {"a", "b"},
- {"foo/bar/baz", "foo/bar/baz/"}
- };
- auto TestFn = [](path const& LHS, const directory_entry& LHSE,
- path const& RHS, const directory_entry& RHSE) {
- assert((LHS == RHS) == (LHSE == RHSE));
- assert((LHS != RHS) == (LHSE != RHSE));
- assert((LHS < RHS) == (LHSE < RHSE));
- assert((LHS <= RHS) == (LHSE <= RHSE));
- assert((LHS > RHS) == (LHSE > RHSE));
- assert((LHS >= RHS) == (LHSE >= RHSE));
- };
+ TestType TestCases[] = {{"", ""}, {"", "a"}, {"a", "a"}, {"a", "b"}, {"foo/bar/baz", "foo/bar/baz/"}};
for (auto const& TC : TestCases) {
- const directory_entry L(TC.first);
- const directory_entry R(TC.second);
- TestFn(TC.first, L, TC.second, R);
- TestFn(TC.second, R, TC.first, L);
+ assert(testComparisonsValues<directory_entry>(TC.first, TC.second));
+ assert(testComparisonsValues<directory_entry>(TC.second, TC.first));
+#if TEST_STD_VER > 17
+ assert(testOrderValues<directory_entry>(TC.first, TC.second));
+ assert(testOrderValues<directory_entry>(TC.second, TC.first));
+#endif
}
-}
-
-int main(int, char**) {
- test_comparison_signatures();
- test_comparisons_simple();
return 0;
}
More information about the libcxx-commits
mailing list