diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -182,7 +182,7 @@ "`3712 `__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","July 2022","","","|ranges|" "`3713 `__","Sorted with respect to comparator (only)","July 2022","","" "`3715 `__","``view_interface::empty`` is overconstrained","July 2022","","","|ranges|" -"`3719 `__","Directory iterators should be usable with default sentinel","July 2022","","","|ranges|" +"`3719 `__","Directory iterators should be usable with default sentinel","July 2022","|Complete|","17.0","|ranges|" "`3721 `__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|" "`3724 `__","``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 --- 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 @@ _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 --- 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 @@ _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 --- 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 difference_type = ptrdiff_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++23 + 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 difference_type = ptrdiff_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++23 + 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 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -710,7 +710,8 @@ 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++23 + bool operator!=(const regex_iterator&) const; // Removed in C++20 const value_type& operator*() const; const value_type* operator->() const; @@ -768,7 +769,8 @@ 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++23 + 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 @@ #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 @@ = 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 @@ 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 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/equal.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20 + +// + +// class directory_iterator + +// bool operator==(default_sentinel_t) const noexcept { // since C++23 +// return *this == directory_iterator(); +// } + +#include +#include + +#include "filesystem_include.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertEqualityAreNoexcept(); + AssertEqualityReturnBool(); + + { + 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 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/equal.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20 + +// + +// class recursive_directory_iterator + +// bool operator==(default_sentinel_t) const noexcept { // since C++23 +// return *this == recursive_directory_iterator(); +// } + +#include +#include + +#include "filesystem_include.h" +#include "test_comparisons.h" + +int main(int, char**) { + AssertEqualityAreNoexcept(); + AssertEqualityReturnBool(); + + { + 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 --- /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, c++20 + +// + +// class regex_token_iterator + +// bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } // since C++23 + +#include +#include +#include + +#include "test_comparisons.h" + +int main(int, char**) { + AssertEqualityReturnBool(); + + { + std::cregex_iterator i; + assert(testEquality(i, std::default_sentinel, true)); + } + + AssertEqualityReturnBool(); + + { + 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 --- 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 // bool operator==(const regex_token_iterator& right) const; +// bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } // since C++23 // bool operator!=(const regex_token_iterator& right) const; // generated by the compiler in C++20 -#include #include -#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 +#include + +#include "test_comparisons.h" + +int main(int, char**) { +#if _LIBCPP_STD_VER >= 20 + AssertEqualityReturnBool(); + + { + std::cregex_token_iterator i; + assert(testEquality(i, std::default_sentinel, true)); + } + + AssertEqualityReturnBool(); + + { + 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; }