[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