[libc++] LWG3480: make (recursive_)directory_iterator C++20 ranges

Implement LWG3480 which enables `directory_iterator` and
`recursive_directory_iterator` to be both a `borrowed_range` and a
`view`.

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D111644
This commit is contained in:
Joe Loser 2021-10-14 11:53:43 -04:00
parent e4e48e2f02
commit 1fa27f2a10
No known key found for this signature in database
GPG Key ID: 1CDBEBC050EA230D
9 changed files with 165 additions and 38 deletions

View File

@ -110,7 +110,7 @@
`3407 <https://wg21.link/LWG3407>`__,"Some problems with the wording changes of P1739R4","October 2021","",""
`3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","",""
`3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","",""
`3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","",""
`3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","|Complete|","14.0"
`3498 <https://wg21.link/LWG3498>`__,"Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","October 2021","",""
`3535 <https://wg21.link/LWG3535>`__,"``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie","October 2021","",""
`3554 <https://wg21.link/LWG3554>`__,"``chrono::parse`` needs ``const charT*`` and ``basic_string_view<charT>`` overloads","October 2021","",""

1 Issue # Issue Name Meeting Status First released version
110 `3407 <https://wg21.link/LWG3407>`__ Some problems with the wording changes of P1739R4 October 2021
111 `3422 <https://wg21.link/LWG3422>`__ Issues of ``seed_seq``'s constructors October 2021
112 `3470 <https://wg21.link/LWG3470>`__ ``convertible-to-non-slicing`` seems to reject valid case October 2021
113 `3480 <https://wg21.link/LWG3480>`__ ``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges October 2021 |Complete| 14.0
114 `3498 <https://wg21.link/LWG3498>`__ Inconsistent ``noexcept``-specifiers for ``basic_syncbuf`` October 2021
115 `3535 <https://wg21.link/LWG3535>`__ ``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie October 2021
116 `3554 <https://wg21.link/LWG3554>`__ ``chrono::parse`` needs ``const charT*`` and ``basic_string_view<charT>`` overloads October 2021

View File

@ -85,7 +85,7 @@
`LWG3392 <https://wg21.link/LWG3392>`__,"``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel",,
`LWG3407 <https://wg21.link/LWG3407>`__,"Some problems with the wording changes of P1739R4",,
`LWG3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case",,
`LWG3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges",,
`LWG3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","|Complete|","14.0"
`LWG3535 <https://wg21.link/LWG3535>`__,"``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie",,
`LWG3559 <https://wg21.link/LWG3559>`__,"Semantic requirements of ``sized_range`` is circular",,
`LWG3560 <https://wg21.link/LWG3560>`__,"``ranges::equal`` and ``ranges::is_permutation`` should short-circuit for ``sized_ranges``",,

1 Number Name Status First released version
85 `LWG3480 <https://wg21.link/LWG3480>`__ ``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges |Complete| 14.0
86 `LWG3535 <https://wg21.link/LWG3535>`__ ``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie
87 `LWG3559 <https://wg21.link/LWG3559>`__ Semantic requirements of ``sized_range`` is circular
88 `LWG3560 <https://wg21.link/LWG3560>`__ ``ranges::equal`` and ``ranges::is_permutation`` should short-circuit for ``sized_ranges``
89 `LWG3563 <https://wg21.link/LWG3563>`__ ``keys_view`` example is broken
90 `LWG3568 <https://wg21.link/LWG3568>`__ ``basic_istream_view`` needs to initialize ``value_``
91 `LWG3572 <https://wg21.link/LWG3572>`__ ``copyable-box`` should be fully ``constexpr``

View File

@ -11,7 +11,7 @@
/*
filesystem synopsis
namespace std { namespace filesystem {
namespace std::filesystem {
class path;
@ -48,13 +48,13 @@
// enable directory_iterator range-based for statements
directory_iterator begin(directory_iterator iter) noexcept;
directory_iterator end(const directory_iterator&) noexcept;
directory_iterator end(directory_iterator) noexcept;
class recursive_directory_iterator;
// enable recursive_directory_iterator range-based for statements
recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
recursive_directory_iterator end(recursive_directory_iterator) noexcept;
class file_status;
@ -224,14 +224,25 @@
path weakly_canonical(path const& p);
path weakly_canonical(path const& p, error_code& ec);
} // namespace std::filesystem
} } // namespaces std::filesystem
template <>
inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::directory_iterator> = true;
template <>
inline constexpr bool std::ranges::enable_borrowed_range<std::filesystem::recursive_directory_iterator> = true;
template <>
inline constexpr bool std::ranges::enable_view<std::filesystem::directory_iterator> = true;
template <>
inline constexpr bool std::ranges::enable_view<std::filesystem::recursive_directory_iterator> = true;
*/
#include <__availability>
#include <__config>
#include <__debug>
#include <__ranges/enable_borrowed_range.h>
#include <__ranges/enable_view.h>
#include <__utility/forward.h>
#include <chrono>
#include <compare>
@ -2869,7 +2880,7 @@ begin(directory_iterator __iter) noexcept {
}
inline _LIBCPP_INLINE_VISIBILITY directory_iterator
end(const directory_iterator&) noexcept {
end(directory_iterator) noexcept {
return directory_iterator();
}
@ -3001,7 +3012,7 @@ begin(recursive_directory_iterator __iter) noexcept {
}
inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
end(const recursive_directory_iterator&) noexcept {
end(recursive_directory_iterator) noexcept {
return recursive_directory_iterator();
}
@ -3009,6 +3020,18 @@ _LIBCPP_AVAILABILITY_FILESYSTEM_POP
_LIBCPP_END_NAMESPACE_FILESYSTEM
#if !defined(_LIBCPP_HAS_NO_RANGES)
template <>
inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true;
template <>
inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true;
template <>
inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true;
template <>
inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true;
#endif
#endif // !_LIBCPP_CXX03_LANG
_LIBCPP_POP_MACROS

View File

@ -30,12 +30,16 @@ TEST_SUITE(directory_iterator_begin_end_tests)
TEST_CASE(test_function_signatures)
{
directory_iterator d; ((void)d);
directory_iterator d;
ASSERT_SAME_TYPE(decltype(begin(d)), directory_iterator);
ASSERT_SAME_TYPE(decltype(begin(std::move(d))), directory_iterator);
ASSERT_NOEXCEPT(begin(d));
ASSERT_NOEXCEPT(begin(std::move(d)));
ASSERT_SAME_TYPE(decltype(end(d)), directory_iterator);
ASSERT_SAME_TYPE(decltype(end(std::move(d))), directory_iterator);
ASSERT_NOEXCEPT(end(d));
ASSERT_NOEXCEPT(end(std::move(d)));
}

View File

@ -9,45 +9,35 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// XFAIL: *
// directory_iterator, recursive_directory_iterator
// directory_iterator
#include "filesystem_include.h"
#include <concepts>
#include <ranges>
static_assert(std::same_as<std::ranges::iterator_t<fs::directory_iterator>, fs::directory_iterator>);
static_assert(std::ranges::common_range<fs::directory_iterator>);
static_assert(std::ranges::input_range<fs::directory_iterator>);
static_assert(!std::ranges::view<fs::directory_iterator>);
static_assert(std::ranges::view<fs::directory_iterator>);
static_assert(!std::ranges::sized_range<fs::directory_iterator>);
static_assert(!std::ranges::borrowed_range<fs::directory_iterator>);
static_assert(!std::ranges::viewable_range<fs::directory_iterator>);
static_assert(std::ranges::borrowed_range<fs::directory_iterator>);
static_assert(std::ranges::viewable_range<fs::directory_iterator>);
static_assert(std::same_as<std::ranges::iterator_t<fs::directory_iterator const>, fs::directory_iterator>);
static_assert(std::ranges::common_range<fs::directory_iterator const>);
static_assert(std::ranges::input_range<fs::directory_iterator const>);
static_assert(!std::ranges::view<fs::directory_iterator const>);
static_assert(!std::ranges::sized_range<fs::directory_iterator const>);
static_assert(!std::ranges::borrowed_range<fs::directory_iterator const>);
static_assert(!std::ranges::viewable_range<fs::directory_iterator const>);
static_assert(std::same_as<std::ranges::iterator_t<fs::directory_iterator&>, fs::directory_iterator>);
static_assert(std::ranges::common_range<fs::directory_iterator&>);
static_assert(std::ranges::input_range<fs::directory_iterator&>);
static_assert(!std::ranges::view<fs::directory_iterator&>);
static_assert(!std::ranges::sized_range<fs::directory_iterator&>);
static_assert(std::ranges::borrowed_range<fs::directory_iterator&>);
static_assert(std::ranges::viewable_range<fs::directory_iterator&>);
static_assert(std::same_as<std::ranges::iterator_t<fs::recursive_directory_iterator>, fs::recursive_directory_iterator>);
static_assert(std::ranges::common_range<fs::recursive_directory_iterator>);
static_assert(std::ranges::input_range<fs::recursive_directory_iterator>);
static_assert(!std::ranges::view<fs::recursive_directory_iterator>);
static_assert(!std::ranges::sized_range<fs::recursive_directory_iterator>);
static_assert(!std::ranges::borrowed_range<fs::recursive_directory_iterator>);
static_assert(!std::ranges::viewable_range<fs::recursive_directory_iterator>);
static_assert(std::same_as<std::ranges::iterator_t<const fs::directory_iterator&>, fs::directory_iterator>);
static_assert(std::ranges::common_range<const fs::directory_iterator&>);
static_assert(std::ranges::input_range<const fs::directory_iterator&>);
static_assert(!std::ranges::view<const fs::directory_iterator&>);
static_assert(!std::ranges::sized_range<const fs::directory_iterator&>);
static_assert(std::ranges::borrowed_range<const fs::directory_iterator&>);
static_assert(std::ranges::viewable_range<const fs::directory_iterator&>);
static_assert(std::same_as<std::ranges::iterator_t<fs::recursive_directory_iterator const>, fs::recursive_directory_iterator>);
static_assert(std::ranges::common_range<fs::recursive_directory_iterator const>);
static_assert(std::ranges::input_range<fs::recursive_directory_iterator const>);
static_assert(!std::ranges::view<fs::recursive_directory_iterator const>);
static_assert(!std::ranges::sized_range<fs::recursive_directory_iterator const>);
static_assert(!std::ranges::borrowed_range<fs::recursive_directory_iterator const>);
static_assert(!std::ranges::viewable_range<fs::recursive_directory_iterator const>);

View File

@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// recursive_directory_iterator
#include "filesystem_include.h"
#include <concepts>
#include <ranges>
static_assert(std::same_as<std::ranges::iterator_t<fs::recursive_directory_iterator>, fs::recursive_directory_iterator>);
static_assert(std::ranges::common_range<fs::recursive_directory_iterator>);
static_assert(std::ranges::input_range<fs::recursive_directory_iterator>);
static_assert(std::ranges::view<fs::recursive_directory_iterator>);
static_assert(!std::ranges::sized_range<fs::recursive_directory_iterator>);
static_assert(std::ranges::borrowed_range<fs::recursive_directory_iterator>);
static_assert(std::ranges::viewable_range<fs::recursive_directory_iterator>);
static_assert(std::same_as<std::ranges::iterator_t<fs::recursive_directory_iterator&>, fs::recursive_directory_iterator>);
static_assert(std::ranges::common_range<fs::recursive_directory_iterator&>);
static_assert(std::ranges::input_range<fs::recursive_directory_iterator&>);
static_assert(!std::ranges::view<fs::recursive_directory_iterator&>);
static_assert(!std::ranges::sized_range<fs::recursive_directory_iterator&>);
static_assert(std::ranges::borrowed_range<fs::recursive_directory_iterator&>);
static_assert(std::ranges::viewable_range<fs::recursive_directory_iterator&>);
static_assert(std::same_as<std::ranges::iterator_t<const fs::recursive_directory_iterator&>, fs::recursive_directory_iterator>);
static_assert(std::ranges::common_range<const fs::recursive_directory_iterator&>);
static_assert(std::ranges::input_range<const fs::recursive_directory_iterator&>);
static_assert(!std::ranges::view<const fs::recursive_directory_iterator&>);
static_assert(!std::ranges::sized_range<const fs::recursive_directory_iterator&>);
static_assert(std::ranges::borrowed_range<const fs::recursive_directory_iterator&>);
static_assert(std::ranges::viewable_range<const fs::recursive_directory_iterator&>);

View File

@ -30,12 +30,16 @@ TEST_SUITE(recursive_directory_iterator_begin_end_tests)
TEST_CASE(test_function_signatures)
{
recursive_directory_iterator d; ((void)d);
recursive_directory_iterator d;
ASSERT_SAME_TYPE(decltype(begin(d)), recursive_directory_iterator);
ASSERT_SAME_TYPE(decltype(begin(std::move(d))), recursive_directory_iterator);
ASSERT_NOEXCEPT(begin(d));
ASSERT_NOEXCEPT(begin(std::move(d)));
ASSERT_SAME_TYPE(decltype(end(d)), recursive_directory_iterator);
ASSERT_SAME_TYPE(decltype(end(std::move(d))), recursive_directory_iterator);
ASSERT_NOEXCEPT(end(d));
ASSERT_NOEXCEPT(end(std::move(d)));
}

View File

@ -0,0 +1,32 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
// <filesystem>
// template <>
// inline constexpr bool ranges::enable_borrowed_range<filesystem::directory_iterator> = true;
// template <>
// inline constexpr bool ranges::enable_borrowed_range<filesystem::recursive_directory_iterator> = true;
#include <filesystem>
#include <ranges>
template<class Range>
void test() {
static_assert(std::ranges::enable_borrowed_range<Range>);
static_assert(!std::ranges::enable_borrowed_range<Range&>);
static_assert(!std::ranges::enable_borrowed_range<const Range>);
}
void test() {
test<std::filesystem::directory_iterator>();
test<std::filesystem::recursive_directory_iterator>();
}

View File

@ -0,0 +1,32 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-concepts
// <filesystem>
// template <>
// inline constexpr bool ranges::enable_view<filesystem::directory_iterator> = true;
// template <>
// inline constexpr bool ranges::enable_view<filesystem::recursive_directory_iterator> = true;
#include <filesystem>
#include <ranges>
template<class Range>
void test() {
static_assert(std::ranges::enable_view<Range>);
static_assert(!std::ranges::enable_view<Range&>);
static_assert(!std::ranges::enable_view<const Range>);
}
void test() {
test<std::filesystem::directory_iterator>();
test<std::filesystem::recursive_directory_iterator>();
}