[libcxx-commits] [libcxx] 5f8e431 - [libc++][ranges] Addresses: LWG3719 - Directory iterators should be usable with default sentinel

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 24 07:54:53 PDT 2023


Author: Hristo Hristov
Date: 2023-06-24T17:54:47+03:00
New Revision: 5f8e4315979c266f3610f89d11a48bd43809533d

URL: https://github.com/llvm/llvm-project/commit/5f8e4315979c266f3610f89d11a48bd43809533d
DIFF: https://github.com/llvm/llvm-project/commit/5f8e4315979c266f3610f89d11a48bd43809533d.diff

LOG: [libc++][ranges] Addresses:  LWG3719 - Directory iterators should be usable with default sentinel

Addresses:  LWG3719 - Directory iterators should be usable with default sentinel
https://wg21.link/LWG3719

Reviewed By: #libc, Mordante

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

Added: 
    libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/equal.pass.cpp
    libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/equal.pass.cpp
    libcxx/test/std/re/re.iter/re.regiter/re.regiter.comp/equal.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx23Issues.csv
    libcxx/include/__filesystem/directory_iterator.h
    libcxx/include/__filesystem/recursive_directory_iterator.h
    libcxx/include/filesystem
    libcxx/include/regex
    libcxx/test/std/re/re.iter/re.tokiter/re.tokiter.comp/equal.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index f8f7259877819..6cfff4dc420c2 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -182,7 +182,7 @@
 "`3712 <https://wg21.link/LWG3712>`__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","July 2022","","","|ranges|"
 "`3713 <https://wg21.link/LWG3713>`__","Sorted with respect to comparator (only)","July 2022","",""
 "`3715 <https://wg21.link/LWG3715>`__","``view_interface::empty`` is overconstrained","July 2022","","","|ranges|"
-"`3719 <https://wg21.link/LWG3719>`__","Directory iterators should be usable with default sentinel","July 2022","","","|ranges|"
+"`3719 <https://wg21.link/LWG3719>`__","Directory iterators should be usable with default sentinel","July 2022","|Complete|","17.0","|ranges|"
 "`3721 <https://wg21.link/LWG3721>`__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|"
 "`3724 <https://wg21.link/LWG3724>`__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0"
 "","","","","",""

diff  --git a/libcxx/include/__filesystem/directory_iterator.h b/libcxx/include/__filesystem/directory_iterator.h
index 2bf17179095f3..5d6b616fd9d84 100644
--- a/libcxx/include/__filesystem/directory_iterator.h
+++ b/libcxx/include/__filesystem/directory_iterator.h
@@ -16,6 +16,7 @@
 #include <__filesystem/directory_entry.h>
 #include <__filesystem/directory_options.h>
 #include <__filesystem/path.h>
+#include <__iterator/default_sentinel.h>
 #include <__iterator/iterator_traits.h>
 #include <__memory/shared_ptr.h>
 #include <__ranges/enable_borrowed_range.h>
@@ -102,6 +103,12 @@ class directory_iterator {
   _LIBCPP_HIDE_FROM_ABI
   directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
 
+#  if _LIBCPP_STD_VER >= 20
+
+  _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept { return *this == directory_iterator(); }
+
+#  endif
+
 private:
   inline _LIBCPP_HIDE_FROM_ABI friend bool
   operator==(const directory_iterator& __lhs,

diff  --git a/libcxx/include/__filesystem/recursive_directory_iterator.h b/libcxx/include/__filesystem/recursive_directory_iterator.h
index e3e50471e9598..b079d6ef70974 100644
--- a/libcxx/include/__filesystem/recursive_directory_iterator.h
+++ b/libcxx/include/__filesystem/recursive_directory_iterator.h
@@ -15,6 +15,7 @@
 #include <__filesystem/directory_entry.h>
 #include <__filesystem/directory_options.h>
 #include <__filesystem/path.h>
+#include <__iterator/default_sentinel.h>
 #include <__iterator/iterator_traits.h>
 #include <__memory/shared_ptr.h>
 #include <__ranges/enable_borrowed_range.h>
@@ -114,6 +115,14 @@ class recursive_directory_iterator {
   _LIBCPP_INLINE_VISIBILITY
   void disable_recursion_pending() { __rec_ = false; }
 
+#  if _LIBCPP_STD_VER >= 20
+
+  _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept {
+    return *this == recursive_directory_iterator();
+  }
+
+#  endif
+
 private:
   _LIBCPP_EXPORTED_FROM_ABI recursive_directory_iterator(const path& __p, directory_options __opt, error_code* __ec);
   _LIBCPP_EXPORTED_FROM_ABI const directory_entry& __dereference() const;

diff  --git a/libcxx/include/filesystem b/libcxx/include/filesystem
index 133c7bea5c802..dfbf7cef3cd56 100644
--- a/libcxx/include/filesystem
+++ b/libcxx/include/filesystem
@@ -236,13 +236,90 @@
       friend class directory_iterator;    // exposition only
     };
 
-    class directory_iterator;
+  class directory_iterator {
+  public:
+    using iterator_category = input_iterator_tag;
+    using value_type        = directory_entry;
+    using 
diff erence_type   = ptr
diff _t;
+    using pointer           = const directory_entry*;
+    using reference         = const directory_entry&;
+
+    // [fs.dir.itr.members], member functions
+    directory_iterator() noexcept;
+    explicit directory_iterator(const path& p);
+    directory_iterator(const path& p, directory_options options);
+    directory_iterator(const path& p, error_code& ec);
+    directory_iterator(const path& p, directory_options options,
+                       error_code& ec);
+    directory_iterator(const directory_iterator& rhs);
+    directory_iterator(directory_iterator&& rhs) noexcept;
+    ~directory_iterator();
+
+    directory_iterator& operator=(const directory_iterator& rhs);
+    directory_iterator& operator=(directory_iterator&& rhs) noexcept;
+
+    const directory_entry& operator*() const;
+    const directory_entry* operator->() const;
+    directory_iterator&    operator++();
+    directory_iterator&    increment(error_code& ec);
+
+    bool operator==(default_sentinel_t) const noexcept {          // since C++20
+      return *this == directory_iterator();
+    }
+
+    // other members as required by [input.iterators], input iterators
+  };
 
     // enable directory_iterator range-based for statements
     directory_iterator begin(directory_iterator iter) noexcept;
     directory_iterator end(directory_iterator) noexcept;
 
-    class recursive_directory_iterator;
+class recursive_directory_iterator {
+  public:
+    using iterator_category = input_iterator_tag;
+    using value_type        = directory_entry;
+    using 
diff erence_type   = ptr
diff _t;
+    using pointer           = const directory_entry*;
+    using reference         = const directory_entry&;
+
+    // [fs.rec.dir.itr.members], constructors and destructor
+    recursive_directory_iterator() noexcept;
+    explicit recursive_directory_iterator(const path& p);
+    recursive_directory_iterator(const path& p, directory_options options);
+    recursive_directory_iterator(const path& p, directory_options options,
+                                 error_code& ec);
+    recursive_directory_iterator(const path& p, error_code& ec);
+    recursive_directory_iterator(const recursive_directory_iterator& rhs);
+    recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
+    ~recursive_directory_iterator();
+
+    // [fs.rec.dir.itr.members], observers
+    directory_options  options() const;
+    int                depth() const;
+    bool               recursion_pending() const;
+
+    const directory_entry& operator*() const;
+    const directory_entry* operator->() const;
+
+    // [fs.rec.dir.itr.members], modifiers
+    recursive_directory_iterator&
+      operator=(const recursive_directory_iterator& rhs);
+    recursive_directory_iterator&
+      operator=(recursive_directory_iterator&& rhs) noexcept;
+
+    recursive_directory_iterator& operator++();
+    recursive_directory_iterator& increment(error_code& ec);
+
+    void pop();
+    void pop(error_code& ec);
+    void disable_recursion_pending();
+
+    bool operator==(default_sentinel_t) const noexcept {          // since C++20
+      return *this == recursive_directory_iterator();
+    }
+
+    // other members as required by [input.iterators], input iterators
+  };
 
     // enable recursive_directory_iterator range-based for statements
     recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;

diff  --git a/libcxx/include/regex b/libcxx/include/regex
index dce58c769de52..d72c5e1c0be8d 100644
--- a/libcxx/include/regex
+++ b/libcxx/include/regex
@@ -710,7 +710,8 @@ public:
     regex_iterator& operator=(const regex_iterator&);
 
     bool operator==(const regex_iterator&) const;
-    bool operator!=(const regex_iterator&) const;                                // Removed in C++20
+    bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } // since C++20
+    bool operator!=(const regex_iterator&) const;                                   // Removed in C++20
 
     const value_type& operator*() const;
     const value_type* operator->() const;
@@ -768,7 +769,8 @@ public:
     regex_token_iterator& operator=(const regex_token_iterator&);
 
     bool operator==(const regex_token_iterator&) const;
-    bool operator!=(const regex_token_iterator&) const;                  // Removed in C++20
+    bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } // since C++20
+    bool operator!=(const regex_token_iterator&) const;                                   // Removed in C++20
 
     const value_type& operator*() const;
     const value_type* operator->() const;
@@ -791,6 +793,7 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator;
 #include <__availability>
 #include <__config>
 #include <__iterator/back_insert_iterator.h>
+#include <__iterator/default_sentinel.h>
 #include <__iterator/wrap_iter.h>
 #include <__locale>
 #include <__memory_resource/polymorphic_allocator.h>
@@ -6429,7 +6432,10 @@ public:
                                      = regex_constants::match_default) = delete;
 #endif
 
-    bool operator==(const regex_iterator& __x) const;
+    _LIBCPP_HIDE_FROM_ABI bool operator==(const regex_iterator& __x) const;
+#if _LIBCPP_STD_VER >= 20
+    _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const { return *this == regex_iterator(); }
+#endif
 #if _LIBCPP_STD_VER < 20
     _LIBCPP_INLINE_VISIBILITY
     bool operator!=(const regex_iterator& __x) const {return !(*this == __x);}
@@ -6609,9 +6615,14 @@ public:
     regex_token_iterator(const regex_token_iterator&);
     regex_token_iterator& operator=(const regex_token_iterator&);
 
-    bool operator==(const regex_token_iterator& __x) const;
-    _LIBCPP_INLINE_VISIBILITY
+    _LIBCPP_HIDE_FROM_ABI bool operator==(const regex_token_iterator& __x) const;
+#if _LIBCPP_STD_VER >= 20
+    _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const {
+        return *this == regex_token_iterator();
+    }
+#endif
 #if _LIBCPP_STD_VER < 20
+    _LIBCPP_INLINE_VISIBILITY
     bool operator!=(const regex_token_iterator& __x) const {return !(*this == __x);}
 #endif
 

diff  --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/equal.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/equal.pass.cpp
new file mode 100644
index 0000000000000..5299eb0451de0
--- /dev/null
+++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/equal.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <filesystem>
+
+// class directory_iterator
+
+// bool operator==(default_sentinel_t) const noexcept {           // since C++20
+//   return *this == directory_iterator();
+// }
+
+#include <cassert>
+#include <iterator>
+
+#include "filesystem_include.h"
+#include "test_comparisons.h"
+
+int main(int, char**) {
+  AssertEqualityAreNoexcept<fs::directory_iterator>();
+  AssertEqualityReturnBool<fs::directory_iterator>();
+
+  fs::directory_iterator i;
+  assert(testEquality(i, std::default_sentinel, true));
+
+  return 0;
+}

diff  --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/equal.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/equal.pass.cpp
new file mode 100644
index 0000000000000..1616bcf1300a3
--- /dev/null
+++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/equal.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// bool operator==(default_sentinel_t) const noexcept {           // since C++20
+//   return *this == recursive_directory_iterator();
+// }
+
+#include <cassert>
+#include <iterator>
+
+#include "filesystem_include.h"
+#include "test_comparisons.h"
+
+int main(int, char**) {
+  AssertEqualityAreNoexcept<fs::recursive_directory_iterator>();
+  AssertEqualityReturnBool<fs::recursive_directory_iterator>();
+
+  fs::recursive_directory_iterator i;
+  assert(testEquality(i, std::default_sentinel, true));
+
+  return 0;
+}

diff  --git a/libcxx/test/std/re/re.iter/re.regiter/re.regiter.comp/equal.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/re.regiter.comp/equal.pass.cpp
new file mode 100644
index 0000000000000..6c0b16f50c414
--- /dev/null
+++ b/libcxx/test/std/re/re.iter/re.regiter/re.regiter.comp/equal.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <regex>
+
+// class regex_token_iterator<BidirectionalIterator, charT, traits>
+
+// bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } // since C++20
+
+#include <cassert>
+#include <iterator>
+#include <regex>
+
+#include "test_comparisons.h"
+
+int main(int, char**) {
+  AssertEqualityReturnBool<std::cregex_iterator>();
+
+  {
+    std::cregex_iterator i;
+    assert(testEquality(i, std::default_sentinel, true));
+  }
+
+  AssertEqualityReturnBool<std::sregex_token_iterator>();
+
+  {
+    std::sregex_token_iterator i;
+    assert(testEquality(i, std::default_sentinel, true));
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/re/re.iter/re.tokiter/re.tokiter.comp/equal.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/re.tokiter.comp/equal.pass.cpp
index 7ccb700c1d182..ef0fd5cd111ad 100644
--- a/libcxx/test/std/re/re.iter/re.tokiter/re.tokiter.comp/equal.pass.cpp
+++ b/libcxx/test/std/re/re.iter/re.tokiter/re.tokiter.comp/equal.pass.cpp
@@ -11,28 +11,45 @@
 // class regex_token_iterator<BidirectionalIterator, charT, traits>
 
 // bool operator==(const regex_token_iterator& right) const;
+// bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } // since C++20
 // bool operator!=(const regex_token_iterator& right) const; // generated by the compiler in C++20
 
-#include <regex>
 #include <cassert>
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    {
-        std::regex phone_numbers("\\d{3}-\\d{4}");
-        const char phone_book[] = "start 555-1234, 555-2345, 555-3456 end";
-        std::cregex_token_iterator i(std::begin(phone_book), std::end(phone_book)-1,
-                                     phone_numbers, -1);
-        assert(i != std::cregex_token_iterator());
-        assert(!(i == std::cregex_token_iterator()));
-        std::cregex_token_iterator i2 = i;
-        assert(i2 == i);
-        assert(!(i2 != i));
-        ++i;
-        assert(!(i2 == i));
-        assert(i2 != i);
-    }
+#include <iterator>
+#include <regex>
+
+#include "test_comparisons.h"
+
+int main(int, char**) {
+#if _LIBCPP_STD_VER >= 20
+  AssertEqualityReturnBool<std::cregex_token_iterator>();
+
+  {
+    std::cregex_token_iterator i;
+    assert(testEquality(i, std::default_sentinel, true));
+  }
+
+  AssertEqualityReturnBool<std::sregex_token_iterator>();
+
+  {
+    std::sregex_token_iterator i;
+    assert(testEquality(i, std::default_sentinel, true));
+  }
+#endif
+
+  {
+    std::regex phone_numbers("\\d{3}-\\d{4}");
+    const char phone_book[] = "start 555-1234, 555-2345, 555-3456 end";
+    std::cregex_token_iterator i(std::begin(phone_book), std::end(phone_book) - 1, phone_numbers, -1);
+    assert(i != std::cregex_token_iterator());
+    assert(!(i == std::cregex_token_iterator()));
+    std::cregex_token_iterator i2 = i;
+    assert(i2 == i);
+    assert(!(i2 != i));
+    ++i;
+    assert(!(i2 == i));
+    assert(i2 != i);
+  }
 
   return 0;
 }


        


More information about the libcxx-commits mailing list