diff options
Diffstat (limited to 'libcxx/include/__ranges')
37 files changed, 1862 insertions, 397 deletions
diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h index 0f1cca033a23..e48a71adf7e8 100644 --- a/libcxx/include/__ranges/access.h +++ b/libcxx/include/__ranges/access.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_ACCESS_H #define _LIBCPP___RANGES_ACCESS_H @@ -14,8 +15,13 @@ #include <__iterator/concepts.h> #include <__iterator/readable_traits.h> #include <__ranges/enable_borrowed_range.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> +#include <__utility/declval.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -99,7 +105,7 @@ inline namespace __cpo { namespace ranges { template <class _Tp> - using iterator_t = decltype(ranges::begin(declval<_Tp&>())); + using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); } // namespace ranges // [range.access.end] diff --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h index 181477419c85..511f7b3b46f3 100644 --- a/libcxx/include/__ranges/all.h +++ b/libcxx/include/__ranges/all.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_ALL_H #define _LIBCPP___RANGES_ALL_H @@ -28,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges::views { @@ -72,11 +73,11 @@ inline namespace __cpo { } // namespace __cpo template<ranges::viewable_range _Range> -using all_t = decltype(views::all(declval<_Range>())); +using all_t = decltype(views::all(std::declval<_Range>())); } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h new file mode 100644 index 000000000000..422d8a8e0834 --- /dev/null +++ b/libcxx/include/__ranges/as_rvalue_view.h @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_AS_RVALUE_H +#define _LIBCPP___RANGES_AS_RVALUE_H + +#include <__concepts/constructible.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/move_iterator.h> +#include <__iterator/move_sentinel.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +template <view _View> + requires input_range<_View> +class as_rvalue_view : public view_interface<as_rvalue_view<_View>> { + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + +public: + _LIBCPP_HIDE_FROM_ABI as_rvalue_view() + requires default_initializable<_View> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit as_rvalue_view(_View __base) : __base_(std::move(__base)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() + requires(!__simple_view<_View>) + { + return move_iterator(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range<const _View> + { + return move_iterator(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View>) + { + if constexpr (common_range<_View>) { + return move_iterator(ranges::end(__base_)); + } else { + return move_sentinel(ranges::end(__base_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range<const _View> + { + if constexpr (common_range<const _View>) { + return move_iterator(ranges::end(__base_)); + } else { + return move_sentinel(ranges::end(__base_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_View> + { + return ranges::size(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range<const _View> + { + return ranges::size(__base_); + } +}; + +template <class _Range> +as_rvalue_view(_Range&&) -> as_rvalue_view<views::all_t<_Range>>; + +template <class _View> +inline constexpr bool enable_borrowed_range<as_rvalue_view<_View>> = enable_borrowed_range<_View>; + +namespace views { +namespace __as_rvalue { +struct __fn : __range_adaptor_closure<__fn> { + template <class _Range> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + noexcept(noexcept(/**/ as_rvalue_view(std::forward<_Range>(__range)))) + -> decltype(/*--*/ as_rvalue_view(std::forward<_Range>(__range))) { + return /*-------------*/ as_rvalue_view(std::forward<_Range>(__range)); + } + + template <class _Range> + requires same_as<range_rvalue_reference_t<_Range>, range_reference_t<_Range>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + noexcept(noexcept(/**/ views::all(std::forward<_Range>(__range)))) + -> decltype(/*--*/ views::all(std::forward<_Range>(__range))) { + return /*-------------*/ views::all(std::forward<_Range>(__range)); + } +}; +} // namespace __as_rvalue + +inline namespace __cpo { +constexpr auto as_rvalue = __as_rvalue::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___RANGES_AS_RVALUE_H diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h index 61b9b61f26aa..8d7ae5841579 100644 --- a/libcxx/include/__ranges/common_view.h +++ b/libcxx/include/__ranges/common_view.h @@ -6,9 +6,12 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_COMMON_VIEW_H #define _LIBCPP___RANGES_COMMON_VIEW_H +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> #include <__config> #include <__iterator/common_iterator.h> #include <__iterator/iterator_traits.h> @@ -21,7 +24,6 @@ #include <__ranges/view_interface.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -30,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -128,7 +130,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h index 87df1d18baf8..e34c545578ab 100644 --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_CONCEPTS_H #define _LIBCPP___RANGES_CONCEPTS_H @@ -23,8 +24,12 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <initializer_list> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -54,7 +59,7 @@ namespace ranges { // `iterator_t` defined in <__ranges/access.h> template <range _Rp> - using sentinel_t = decltype(ranges::end(declval<_Rp&>())); + using sentinel_t = decltype(ranges::end(std::declval<_Rp&>())); template <range _Rp> using range_difference_t = iter_difference_t<iterator_t<_Rp>>; @@ -73,7 +78,7 @@ namespace ranges { concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; template<sized_range _Rp> - using range_size_t = decltype(ranges::size(declval<_Rp&>())); + using range_size_t = decltype(ranges::size(std::declval<_Rp&>())); // `disable_sized_range` defined in `<__ranges/size.h>` diff --git a/libcxx/include/__ranges/copyable_box.h b/libcxx/include/__ranges/copyable_box.h index 6012497db5e8..fb3d6e409c8f 100644 --- a/libcxx/include/__ranges/copyable_box.h +++ b/libcxx/include/__ranges/copyable_box.h @@ -10,11 +10,13 @@ #ifndef _LIBCPP___RANGES_COPYABLE_BOX_H #define _LIBCPP___RANGES_COPYABLE_BOX_H +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/movable.h> #include <__config> #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__utility/move.h> -#include <concepts> #include <optional> #include <type_traits> @@ -24,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 // __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into // a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state @@ -171,7 +173,7 @@ namespace ranges { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/counted.h b/libcxx/include/__ranges/counted.h index f45f1e890085..138aa0e1dde5 100644 --- a/libcxx/include/__ranges/counted.h +++ b/libcxx/include/__ranges/counted.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_COUNTED_H #define _LIBCPP___RANGES_COUNTED_H @@ -29,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges::views { @@ -74,7 +75,7 @@ inline namespace __cpo { } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/dangling.h b/libcxx/include/__ranges/dangling.h index 525b5ff0aabe..c10453454dc3 100644 --- a/libcxx/include/__ranges/dangling.h +++ b/libcxx/include/__ranges/dangling.h @@ -13,7 +13,7 @@ #include <__config> #include <__ranges/access.h> #include <__ranges/concepts.h> -#include <type_traits> +#include <__type_traits/conditional.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h index 35d1af1e648f..0ac25b52c727 100644 --- a/libcxx/include/__ranges/data.h +++ b/libcxx/include/__ranges/data.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_DATA_H #define _LIBCPP___RANGES_DATA_H @@ -15,8 +16,13 @@ #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_pointer.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h index b2a8ee581475..8f3564a8c760 100644 --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -6,11 +6,14 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_DROP_VIEW_H #define _LIBCPP___RANGES_DROP_VIEW_H #include <__algorithm/min.h> #include <__assert> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> #include <__config> #include <__functional/bind_back.h> #include <__fwd/span.h> @@ -33,7 +36,6 @@ #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -45,7 +47,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<view _View> @@ -297,7 +299,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/drop_while_view.h b/libcxx/include/__ranges/drop_while_view.h new file mode 100644 index 000000000000..7c28992f1874 --- /dev/null +++ b/libcxx/include/__ranges/drop_while_view.h @@ -0,0 +1,129 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_DROP_WHILE_VIEW_H +#define _LIBCPP___RANGES_DROP_WHILE_VIEW_H + +#include <__algorithm/ranges_find_if_not.h> +#include <__assert> +#include <__concepts/constructible.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/reference_wrapper.h> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/copyable_box.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <view _View, class _Pred> + requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> +class drop_while_view : public view_interface<drop_while_view<_View, _Pred>> { +public: + _LIBCPP_HIDE_FROM_ABI drop_while_view() + requires default_initializable<_View> && default_initializable<_Pred> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr drop_while_view(_View __base, _Pred __pred) + : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { + _LIBCPP_ASSERT(__pred_.__has_value(), + "drop_while_view needs to have a non-empty predicate before calling begin() -- did a previous " + "assignment to this drop_while_view fail?"); + if constexpr (_UseCache) { + if (!__cached_begin_.__has_value()) { + __cached_begin_.__emplace(ranges::find_if_not(__base_, std::cref(*__pred_))); + } + return *__cached_begin_; + } else { + return ranges::find_if_not(__base_, std::cref(*__pred_)); + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() { return ranges::end(__base_); } + +private: + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + + static constexpr bool _UseCache = forward_range<_View>; + using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); +}; + +template <class _View, class _Pred> +inline constexpr bool enable_borrowed_range<drop_while_view<_View, _Pred>> = enable_borrowed_range<_View>; + +template <class _Range, class _Pred> +drop_while_view(_Range&&, _Pred) -> drop_while_view<views::all_t<_Range>, _Pred>; + +namespace views { +namespace __drop_while { + +struct __fn { + template <class _Range, class _Pred> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const + noexcept(noexcept(/**/ drop_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) + -> decltype(/*--*/ drop_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) { + return /*-------------*/ drop_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)); + } + + template <class _Pred> + requires constructible_from<decay_t<_Pred>, _Pred> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const + noexcept(is_nothrow_constructible_v<decay_t<_Pred>, _Pred>) { + return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred))); + } +}; + +} // namespace __drop_while + +inline namespace __cpo { +inline constexpr auto drop_while = __drop_while::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_DROP_WHILE_VIEW_H diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h new file mode 100644 index 000000000000..3afd6ddbe8f2 --- /dev/null +++ b/libcxx/include/__ranges/elements_view.h @@ -0,0 +1,423 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_ELEMENTS_VIEW_H +#define _LIBCPP___RANGES_ELEMENTS_VIEW_H + +#include <__compare/three_way_comparable.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__config> +#include <__fwd/get.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_like.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <class _View, size_t _Np, bool _Const> +class __elements_view_iterator; + +template <class _View, size_t _Np, bool _Const> +class __elements_view_sentinel; + +template <class _Tp, size_t _Np> +concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; + +template <class _Tp, size_t _Np> +concept __returnable_element = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Np, _Tp>>; + +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +class elements_view : public view_interface<elements_view<_View, _Np>> { +public: + _LIBCPP_HIDE_FROM_ABI elements_view() + requires default_initializable<_View> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit elements_view(_View __base) : __base_(std::move(__base)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() + requires(!__simple_view<_View>) + { + return __iterator</*_Const=*/false>(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires range<const _View> + { + return __iterator</*_Const=*/true>(ranges::begin(__base_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View> && !common_range<_View>) + { + return __sentinel</*_Const=*/false>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View> && common_range<_View>) + { + return __iterator</*_Const=*/false>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires range<const _View> + { + return __sentinel</*_Const=*/true>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires common_range<const _View> + { + return __iterator</*_Const=*/true>{ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() + requires sized_range<_View> + { + return ranges::size(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires sized_range<const _View> + { + return ranges::size(__base_); + } + +private: + template <bool _Const> + using __iterator = __elements_view_iterator<_View, _Np, _Const>; + + template <bool _Const> + using __sentinel = __elements_view_sentinel<_View, _Np, _Const>; + + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); +}; + +template <class, size_t> +struct __elements_view_iterator_category_base {}; + +template <forward_range _Base, size_t _Np> +struct __elements_view_iterator_category_base<_Base, _Np> { + static consteval auto __get_iterator_category() { + using _Result = decltype(std::get<_Np>(*std::declval<iterator_t<_Base>>())); + using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; + + if constexpr (!is_lvalue_reference_v<_Result>) { + return input_iterator_tag{}; + } else if constexpr (derived_from<_Cat, random_access_iterator_tag>) { + return random_access_iterator_tag{}; + } else { + return _Cat{}; + } + } + + using iterator_category = decltype(__get_iterator_category()); +}; + +template <class _View, size_t _Np, bool _Const> +class __elements_view_iterator : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { + template <class, size_t, bool > + friend class __elements_view_iterator; + + template <class, size_t, bool > + friend class __elements_view_sentinel; + + using _Base = __maybe_const<_Const, _View>; + + iterator_t<_Base> __current_ = iterator_t<_Base>(); + + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) { + if constexpr (is_reference_v<range_reference_t<_Base>>) { + return std::get<_Np>(*__i); + } else { + using _Element = remove_cv_t<tuple_element_t<_Np, range_reference_t<_Base>>>; + return static_cast<_Element>(std::get<_Np>(*__i)); + } + } + + static consteval auto __get_iterator_concept() { + if constexpr (random_access_range<_Base>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_range<_Base>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_range<_Base>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } + +public: + using iterator_concept = decltype(__get_iterator_concept()); + using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; + using difference_type = range_difference_t<_Base>; + + _LIBCPP_HIDE_FROM_ABI __elements_view_iterator() + requires default_initializable<iterator_t<_Base>> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_iterator(iterator_t<_Base> __current) + : __current_(std::move(__current)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator(__elements_view_iterator<_View, _Np, !_Const> __i) + requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> + : __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; } + + _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator++(int) + requires forward_range<_Base> + { + auto temp = *this; + ++__current_; + return temp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator--() + requires bidirectional_range<_Base> + { + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator--(int) + requires bidirectional_range<_Base> + { + auto temp = *this; + --__current_; + return temp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator+=(difference_type __n) + requires random_access_range<_Base> + { + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator-=(difference_type __n) + requires random_access_range<_Base> + { + __current_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const + requires random_access_range<_Base> + { + return __get_element(__current_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires equality_comparable<iterator_t<_Base>> + { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator<(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> + { + return __x.__current_ < __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator<=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator>=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto + operator<=>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> + { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator + operator+(const __elements_view_iterator& __x, difference_type __y) + requires random_access_range<_Base> + { + return __elements_view_iterator{__x} += __y; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator + operator+(difference_type __x, const __elements_view_iterator& __y) + requires random_access_range<_Base> + { + return __y + __x; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator + operator-(const __elements_view_iterator& __x, difference_type __y) + requires random_access_range<_Base> + { + return __elements_view_iterator{__x} -= __y; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type + operator-(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> + { + return __x.__current_ - __y.__current_; + } +}; + +template <class _View, size_t _Np, bool _Const> +class __elements_view_sentinel { +private: + using _Base = __maybe_const<_Const, _View>; + _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); + + template <class, size_t, bool > + friend class __elements_view_sentinel; + + template <bool _AnyConst> + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) + __get_current(const __elements_view_iterator<_View, _Np, _AnyConst>& __iter) { + return (__iter.__current_); + } + +public: + _LIBCPP_HIDE_FROM_ABI __elements_view_sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_sentinel(sentinel_t<_Base> __end) + : __end_(std::move(__end)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_sentinel(__elements_view_sentinel<_View, _Np, !_Const> __other) + requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> + : __end_(std::move(__other.__end_)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } + + template <bool _OtherConst> + requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + return __get_current(__x) == __y.__end_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> + operator-(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + return __get_current(__x) - __y.__end_; + } + + template <bool _OtherConst> + requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> + operator-(const __elements_view_sentinel& __x, const __elements_view_iterator<_View, _Np, _OtherConst>& __y) { + return __x.__end_ - __get_current(__y); + } +}; + +template <class _Tp, size_t _Np> +inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Np>> = enable_borrowed_range<_Tp>; + +template <class _Tp> +using keys_view = elements_view<_Tp, 0>; +template <class _Tp> +using values_view = elements_view<_Tp, 1>; + +namespace views { +namespace __elements { + +template <size_t _Np> +struct __fn : __range_adaptor_closure<__fn<_Np>> { + template <class _Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const + /**/ noexcept(noexcept(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)))) + /*------*/ -> decltype(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))) { + /*-------------*/ return elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)); + } +}; +} // namespace __elements + +inline namespace __cpo { +template <size_t _Np> +inline constexpr auto elements = __elements::__fn<_Np>{}; +inline constexpr auto keys = elements<0>; +inline constexpr auto values = elements<1>; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_ELEMENTS_VIEW_H diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h index 46c97ca7e329..8a1c75c0bae0 100644 --- a/libcxx/include/__ranges/empty.h +++ b/libcxx/include/__ranges/empty.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_EMPTY_H #define _LIBCPP___RANGES_EMPTY_H @@ -14,7 +15,6 @@ #include <__iterator/concepts.h> #include <__ranges/access.h> #include <__ranges/size.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 // [range.prim.empty] @@ -75,7 +75,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/empty_view.h b/libcxx/include/__ranges/empty_view.h index 3299fe825ddf..58e69ac19f29 100644 --- a/libcxx/include/__ranges/empty_view.h +++ b/libcxx/include/__ranges/empty_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_EMPTY_VIEW_H #define _LIBCPP___RANGES_EMPTY_VIEW_H @@ -20,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<class _Tp> @@ -45,7 +46,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/enable_view.h b/libcxx/include/__ranges/enable_view.h index a1e5721404cd..c85064b915ab 100644 --- a/libcxx/include/__ranges/enable_view.h +++ b/libcxx/include/__ranges/enable_view.h @@ -10,9 +10,12 @@ #ifndef _LIBCPP___RANGES_ENABLE_VIEW_H #define _LIBCPP___RANGES_ENABLE_VIEW_H +#include <__concepts/derived_from.h> +#include <__concepts/same_as.h> #include <__config> -#include <concepts> -#include <type_traits> +#include <__type_traits/is_class.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h index b040ea57b779..f8633a3fee84 100644 --- a/libcxx/include/__ranges/filter_view.h +++ b/libcxx/include/__ranges/filter_view.h @@ -6,10 +6,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_FILTER_VIEW_H #define _LIBCPP___RANGES_FILTER_VIEW_H #include <__algorithm/ranges_find_if.h> +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> #include <__config> #include <__debug> #include <__functional/bind_back.h> @@ -30,7 +35,6 @@ #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -39,9 +43,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { + + template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> + requires view<_View> && is_object_v<_Pred> + class __filter_view_iterator; + + template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> + requires view<_View> && is_object_v<_Pred> + class __filter_view_sentinel; + template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> class filter_view : public view_interface<filter_view<_View, _Pred>> { @@ -54,8 +67,11 @@ namespace ranges { using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); - class __iterator; - class __sentinel; + using __iterator = __filter_view_iterator<_View, _Pred>; + using __sentinel = __filter_view_sentinel<_View, _Pred>; + + friend __iterator; + friend __sentinel; public: _LIBCPP_HIDE_FROM_ABI @@ -115,10 +131,13 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> { + class __filter_view_iterator : public __filter_iterator_category<_View> { + + using __filter_view = filter_view<_View, _Pred>; + public: _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>(); - _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr; + _LIBCPP_NO_UNIQUE_ADDRESS __filter_view* __parent_ = nullptr; using iterator_concept = _If<bidirectional_range<_View>, bidirectional_iterator_tag, @@ -130,10 +149,10 @@ namespace ranges { using difference_type = range_difference_t<_View>; _LIBCPP_HIDE_FROM_ABI - __iterator() requires default_initializable<iterator_t<_View>> = default; + __filter_view_iterator() requires default_initializable<iterator_t<_View>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(filter_view& __parent, iterator_t<_View> __current) + constexpr __filter_view_iterator(__filter_view& __parent, iterator_t<_View> __current) : __current_(std::move(__current)), __parent_(std::addressof(__parent)) { } @@ -152,7 +171,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { + constexpr __filter_view_iterator& operator++() { __current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_), std::ref(*__parent_->__pred_)); return *this; @@ -160,42 +179,42 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) requires forward_range<_View> { + constexpr __filter_view_iterator operator++(int) requires forward_range<_View> { auto __tmp = *this; ++*this; return __tmp; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() requires bidirectional_range<_View> { + constexpr __filter_view_iterator& operator--() requires bidirectional_range<_View> { do { --__current_; } while (!std::invoke(*__parent_->__pred_, *__current_)); return *this; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) requires bidirectional_range<_View> { + constexpr __filter_view_iterator operator--(int) requires bidirectional_range<_View> { auto tmp = *this; --*this; return tmp; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(__iterator const& __x, __iterator const& __y) + friend constexpr bool operator==(__filter_view_iterator const& __x, __filter_view_iterator const& __y) requires equality_comparable<iterator_t<_View>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr range_rvalue_reference_t<_View> iter_move(__iterator const& __it) + friend constexpr range_rvalue_reference_t<_View> iter_move(__filter_view_iterator const& __it) noexcept(noexcept(ranges::iter_move(__it.__current_))) { return ranges::iter_move(__it.__current_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(__iterator const& __x, __iterator const& __y) + friend constexpr void iter_swap(__filter_view_iterator const& __x, __filter_view_iterator const& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) requires indirectly_swappable<iterator_t<_View>> { @@ -205,23 +224,25 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class filter_view<_View, _Pred>::__sentinel { + class __filter_view_sentinel { + using __filter_view = filter_view<_View, _Pred>; + public: sentinel_t<_View> __end_ = sentinel_t<_View>(); _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; + __filter_view_sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel(filter_view& __parent) + constexpr explicit __filter_view_sentinel(__filter_view& __parent) : __end_(ranges::end(__parent.__base_)) { } _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_View> base() const { return __end_; } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(__iterator const& __x, __sentinel const& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(__filter_view_iterator<_View, _Pred> const& __x, __filter_view_sentinel const& __y) { return __x.__current_ == __y.__end_; } }; @@ -252,7 +273,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h index e1f03bafa03a..3654096b7e17 100644 --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_IOTA_VIEW_H #define _LIBCPP___RANGES_IOTA_VIEW_H @@ -39,7 +40,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<class _Int> @@ -82,6 +83,14 @@ namespace ranges { { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>; }; + template <weakly_incrementable _Start> + requires copyable<_Start> + struct __iota_view_iterator; + + template <weakly_incrementable _Start, semiregular _BoundSentinel> + requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> + struct __iota_view_sentinel; + template<class> struct __iota_iterator_category {}; @@ -93,210 +102,9 @@ namespace ranges { template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t> requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> { - struct __iterator : public __iota_iterator_category<_Start> { - friend class iota_view; - - using iterator_concept = - _If<__advanceable<_Start>, random_access_iterator_tag, - _If<__decrementable<_Start>, bidirectional_iterator_tag, - _If<incrementable<_Start>, forward_iterator_tag, - /*Else*/ input_iterator_tag>>>; - - using value_type = _Start; - using difference_type = _IotaDiffT<_Start>; - - _Start __value_ = _Start(); - - _LIBCPP_HIDE_FROM_ABI - __iterator() requires default_initializable<_Start> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { - return __value_; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { - ++__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr void operator++(int) { ++*this; } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) requires incrementable<_Start> { - auto __tmp = *this; - ++*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() requires __decrementable<_Start> { - --__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) requires __decrementable<_Start> { - auto __tmp = *this; - --*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator+=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ += static_cast<_Start>(__n); - } else { - __value_ -= static_cast<_Start>(-__n); - } - } else { - __value_ += __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator-=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ -= static_cast<_Start>(__n); - } else { - __value_ += static_cast<_Start>(-__n); - } - } else { - __value_ -= __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator[](difference_type __n) const - requires __advanceable<_Start> - { - return _Start(__value_ + __n); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) - requires equality_comparable<_Start> - { - return __x.__value_ == __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> - { - return __x.__value_ < __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> - { - return __y < __x; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> - { - return !(__y < __x); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> - { - return !(__x < __y); - } - - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> && three_way_comparable<_Start> - { - return __x.__value_ <=> __y.__value_; - } - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(__iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i += __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(difference_type __n, __iterator __i) - requires __advanceable<_Start> - { - return __i + __n; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator-(__iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i -= __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start>) { - if constexpr (__signed_integer_like<_Start>) { - return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); - } - if (__y.__value_ > __x.__value_) { - return difference_type(-difference_type(__y.__value_ - __x.__value_)); - } - return difference_type(__x.__value_ - __y.__value_); - } - return __x.__value_ - __y.__value_; - } - }; - - struct __sentinel { - friend class iota_view; - - private: - _BoundSentinel __bound_sentinel_ = _BoundSentinel(); - - public: - _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; - constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { - return __x.__value_ == __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return __x.__value_ - __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return -(__y - __x); - } - }; + using __iterator = __iota_view_iterator<_Start>; + using __sentinel = __iota_view_sentinel<_Start, _BoundSentinel>; _Start __value_ = _Start(); _BoundSentinel __bound_sentinel_ = _BoundSentinel(); @@ -377,6 +185,224 @@ namespace ranges { template <class _Start, class _BoundSentinel> inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true; + template <weakly_incrementable _Start> + requires copyable<_Start> + struct __iota_view_iterator : public __iota_iterator_category<_Start> { + + template <weakly_incrementable _StartT, semiregular _BoundSentinelT> + requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> + friend class iota_view; + + using iterator_concept = + _If<__advanceable<_Start>, random_access_iterator_tag, + _If<__decrementable<_Start>, bidirectional_iterator_tag, + _If<incrementable<_Start>, forward_iterator_tag, + /*Else*/ input_iterator_tag>>>; + + using value_type = _Start; + using difference_type = _IotaDiffT<_Start>; + + _Start __value_ = _Start(); + + _LIBCPP_HIDE_FROM_ABI + __iota_view_iterator() requires default_initializable<_Start> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __iota_view_iterator(_Start __value) : __value_(std::move(__value)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { + return __value_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator& operator++() { + ++__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator operator++(int) requires incrementable<_Start> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator& operator--() requires __decrementable<_Start> { + --__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator operator--(int) requires __decrementable<_Start> { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator& operator+=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ += static_cast<_Start>(__n); + } else { + __value_ -= static_cast<_Start>(-__n); + } + } else { + __value_ += __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iota_view_iterator& operator-=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ -= static_cast<_Start>(__n); + } else { + __value_ += static_cast<_Start>(-__n); + } + } else { + __value_ -= __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator[](difference_type __n) const + requires __advanceable<_Start> + { + return _Start(__value_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires equality_comparable<_Start> + { + return __x.__value_ == __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires totally_ordered<_Start> + { + return __x.__value_ < __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires totally_ordered<_Start> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires totally_ordered<_Start> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires totally_ordered<_Start> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto operator<=>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires totally_ordered<_Start> && three_way_comparable<_Start> + { + return __x.__value_ <=> __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iota_view_iterator operator+(__iota_view_iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iota_view_iterator operator+(difference_type __n, __iota_view_iterator __i) + requires __advanceable<_Start> + { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iota_view_iterator operator-(__iota_view_iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr difference_type operator-(const __iota_view_iterator& __x, const __iota_view_iterator& __y) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start>) { + if constexpr (__signed_integer_like<_Start>) { + return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); + } + if (__y.__value_ > __x.__value_) { + return difference_type(-difference_type(__y.__value_ - __x.__value_)); + } + return difference_type(__x.__value_ - __y.__value_); + } + return __x.__value_ - __y.__value_; + } + }; + + template <weakly_incrementable _Start, semiregular _BoundSentinel> + requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> + struct __iota_view_sentinel { + + template <weakly_incrementable _StartT, semiregular _BoundSentinelT> + requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> + friend class iota_view; + + using __iterator = __iota_view_iterator<_Start>; + + private: + _BoundSentinel __bound_sentinel_ = _BoundSentinel(); + + public: + _LIBCPP_HIDE_FROM_ABI + __iota_view_sentinel() = default; + constexpr explicit __iota_view_sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __iota_view_sentinel& __y) { + return __x.__value_ == __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __iota_view_sentinel& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return __x.__value_ - __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __iota_view_sentinel& __x, const __iterator& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return -(__y - __x); + } + }; + namespace views { namespace __iota { struct __fn { @@ -401,7 +427,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/istream_view.h b/libcxx/include/__ranges/istream_view.h new file mode 100644 index 000000000000..69a9df35a4d2 --- /dev/null +++ b/libcxx/include/__ranges/istream_view.h @@ -0,0 +1,149 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_ISTREAM_VIEW_H +#define _LIBCPP___RANGES_ISTREAM_VIEW_H + +#include <__concepts/constructible.h> +#include <__concepts/derived_from.h> +#include <__concepts/movable.h> +#include <__config> +#include <__iterator/default_sentinel.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/view_interface.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> +#include <cstddef> +#include <iosfwd> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template <class _Val, class _CharT, class _Traits> +concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; }; + +template <movable _Val, class _CharT, class _Traits> + requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> +class __basic_istream_view_iterator; + +template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> + requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> +class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { + using __iterator = __basic_istream_view_iterator<_Val, _CharT, _Traits>; + + template <movable _ValueType, class _CharType, class _TraitsType> + requires default_initializable<_ValueType> && __stream_extractable<_ValueType, _CharType, _TraitsType> + friend class __basic_istream_view_iterator; + +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) + : __stream_(std::addressof(__stream)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { + *__stream_ >> __value_; + return __iterator{*this}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; } + +private: + basic_istream<_CharT, _Traits>* __stream_; + _LIBCPP_NO_UNIQUE_ADDRESS _Val __value_ = _Val(); +}; + +template <movable _Val, class _CharT, class _Traits> + requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> +class __basic_istream_view_iterator { +public: + using iterator_concept = input_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = _Val; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __basic_istream_view_iterator( + basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept + : __parent_(std::addressof(__parent)) {} + + __basic_istream_view_iterator(const __basic_istream_view_iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator(__basic_istream_view_iterator&&) = default; + + __basic_istream_view_iterator& operator=(const __basic_istream_view_iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator=(__basic_istream_view_iterator&&) = default; + + _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator++() { + *__parent_->__stream_ >> __parent_->__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; } + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __basic_istream_view_iterator& __x, default_sentinel_t) { + return !*__x.__get_parent_stream(); + } + +private: + basic_istream_view<_Val, _CharT, _Traits>* __parent_; + + _LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const { + return __parent_->__stream_; + } +}; + +template <class _Val> +using istream_view = basic_istream_view<_Val, char>; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <class _Val> +using wistream_view = basic_istream_view<_Val, wchar_t>; +# endif + +namespace views { +namespace __istream { + +// clang-format off +template <class _Tp> +struct __fn { + template <class _Up, class _UnCVRef = remove_cvref_t<_Up>> + requires derived_from<_UnCVRef, basic_istream<typename _UnCVRef::char_type, + typename _UnCVRef::traits_type>> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Up&& __u) const + noexcept(noexcept(basic_istream_view<_Tp, typename _UnCVRef::char_type, + typename _UnCVRef::traits_type>(std::forward<_Up>(__u)))) + -> decltype( basic_istream_view<_Tp, typename _UnCVRef::char_type, + typename _UnCVRef::traits_type>(std::forward<_Up>(__u))) + { return basic_istream_view<_Tp, typename _UnCVRef::char_type, + typename _UnCVRef::traits_type>(std::forward<_Up>(__u)); + } +}; +// clang-format on + +} // namespace __istream + +inline namespace __cpo { +template <class _Tp> +inline constexpr auto istream = __istream::__fn<_Tp>{}; +} // namespace __cpo +} // namespace views + +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___RANGES_ISTREAM_VIEW_H diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index b6fcce95aeda..869540fc99c2 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_JOIN_VIEW_H #define _LIBCPP___RANGES_JOIN_VIEW_H @@ -19,12 +20,16 @@ #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> +#include <__iterator/iterator_with_data.h> +#include <__iterator/segmented_iterator.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> +#include <__ranges/empty.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/maybe_const.h> #include <__utility/forward.h> #include <optional> #include <type_traits> @@ -35,7 +40,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<class> @@ -61,6 +66,14 @@ namespace ranges { >; }; + template <input_range _View, bool _Const> + requires view<_View> && input_range<range_reference_t<_View>> + struct __join_view_iterator; + + template <input_range _View, bool _Const> + requires view<_View> && input_range<range_reference_t<_View>> + struct __join_view_sentinel; + template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> class join_view @@ -68,8 +81,22 @@ namespace ranges { private: using _InnerRange = range_reference_t<_View>; - template<bool> struct __iterator; - template<bool> struct __sentinel; + template<bool _Const> + using __iterator = __join_view_iterator<_View, _Const>; + + template<bool _Const> + using __sentinel = __join_view_sentinel<_View, _Const>; + + template <input_range _View2, bool _Const2> + requires view<_View2> && input_range<range_reference_t<_View2>> + friend struct __join_view_iterator; + + template <input_range _View2, bool _Const2> + requires view<_View2> && input_range<range_reference_t<_View2>> + friend struct __join_view_sentinel; + + template <class> + friend struct std::__segmented_iterator_traits; static constexpr bool _UseCache = !is_reference_v<_InnerRange>; using _Cache = _If<_UseCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>; @@ -137,49 +164,57 @@ namespace ranges { } }; - template<input_range _View> + template<input_range _View, bool _Const> requires view<_View> && input_range<range_reference_t<_View>> - template<bool _Const> struct join_view<_View>::__sentinel { - template<bool> friend struct __sentinel; + struct __join_view_sentinel { + template<input_range _View2, bool> + requires view<_View2> && input_range<range_reference_t<_View2>> + friend struct __join_view_sentinel; private: - using _Parent = __maybe_const<_Const, join_view>; + using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; sentinel_t<_Base> __end_ = sentinel_t<_Base>(); public: _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; + __join_view_sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel(_Parent& __parent) + constexpr explicit __join_view_sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr __sentinel(__sentinel<!_Const> __s) + constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__s.__end_)) {} template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) { return __x.__outer_ == __y.__end_; } }; - template<input_range _View> + template<input_range _View, bool _Const> requires view<_View> && input_range<range_reference_t<_View>> - template<bool _Const> struct join_view<_View>::__iterator + struct __join_view_iterator : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - template<bool> friend struct __iterator; + template<input_range _View2, bool> + requires view<_View2> && input_range<range_reference_t<_View2>> + friend struct __join_view_iterator; + + template <class> + friend struct std::__segmented_iterator_traits; private: - using _Parent = __maybe_const<_Const, join_view>; + using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; using _Outer = iterator_t<_Base>; using _Inner = iterator_t<range_reference_t<_Base>>; + using _InnerRange = range_reference_t<_View>; static constexpr bool __ref_is_glvalue = is_reference_v<range_reference_t<_Base>>; @@ -208,9 +243,12 @@ namespace ranges { __inner_.reset(); } + _LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner) + : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} + public: using iterator_concept = _If< - __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && + __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && common_range<range_reference_t<_Base>>, bidirectional_iterator_tag, _If< @@ -226,17 +264,17 @@ namespace ranges { range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>; _LIBCPP_HIDE_FROM_ABI - __iterator() requires default_initializable<_Outer> = default; + __join_view_iterator() requires default_initializable<_Outer> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(_Parent& __parent, _Outer __outer) + constexpr __join_view_iterator(_Parent& __parent, _Outer __outer) : __outer_(std::move(__outer)) , __parent_(std::addressof(__parent)) { __satisfy(); } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(__iterator<!_Const> __i) + constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i) requires _Const && convertible_to<iterator_t<_View>, _Outer> && convertible_to<iterator_t<_InnerRange>, _Inner> @@ -257,7 +295,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { + constexpr __join_view_iterator& operator++() { auto&& __inner = [&]() -> auto&& { if constexpr (__ref_is_glvalue) return *__outer_; @@ -277,7 +315,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) + constexpr __join_view_iterator operator++(int) requires __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>> @@ -288,7 +326,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() + constexpr __join_view_iterator& operator--() requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -307,7 +345,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) + constexpr __join_view_iterator operator--(int) requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -319,7 +357,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y) requires __ref_is_glvalue && equality_comparable<iterator_t<_Base>> && equality_comparable<iterator_t<range_reference_t<_Base>>> @@ -328,14 +366,14 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __iterator& __i) + friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) { return ranges::iter_move(*__i.__inner_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y) + friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y) noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_))) requires indirectly_swappable<_Inner> { @@ -345,7 +383,7 @@ namespace ranges { template<class _Range> explicit join_view(_Range&&) -> join_view<views::all_t<_Range>>; - + namespace views { namespace __join_view { struct __fn : __range_adaptor_closure<__fn> { @@ -363,7 +401,51 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +template <class _View, bool _Const> + requires(ranges::common_range<typename ranges::__join_view_iterator<_View, _Const>::_Parent> && + __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Outer>::value && + __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Inner>::value) +struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> { + using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>; + + using __segment_iterator = + _LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>; + using __local_iterator = typename _JoinViewIterator::_Inner; + + // TODO: Would it make sense to enable the optimization for other iterator types? + + static constexpr _LIBCPP_HIDE_FROM_ABI __segment_iterator __segment(_JoinViewIterator __iter) { + if (ranges::empty(__iter.__parent_->__base_)) + return {}; + if (!__iter.__inner_.has_value()) + return __segment_iterator(--__iter.__outer_, __iter.__parent_); + return __segment_iterator(__iter.__outer_, __iter.__parent_); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __local(_JoinViewIterator __iter) { + if (ranges::empty(__iter.__parent_->__base_)) + return {}; + if (!__iter.__inner_.has_value()) + return ranges::end(*--__iter.__outer_); + return *__iter.__inner_; + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __begin(__segment_iterator __iter) { + return ranges::begin(*__iter.__get_iter()); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __end(__segment_iterator __iter) { + return ranges::end(*__iter.__get_iter()); + } + + static constexpr _LIBCPP_HIDE_FROM_ABI _JoinViewIterator + __compose(__segment_iterator __seg_iter, __local_iterator __local_iter) { + return _JoinViewIterator( + std::move(__seg_iter).__get_data(), std::move(__seg_iter).__get_iter(), std::move(__local_iter)); + } +}; + +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h index e559a76ef7b7..3a95075884b9 100644 --- a/libcxx/include/__ranges/lazy_split_view.h +++ b/libcxx/include/__ranges/lazy_split_view.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H #define _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H -#include <__algorithm/in_in_result.h> #include <__algorithm/ranges_find.h> #include <__algorithm/ranges_mismatch.h> #include <__concepts/constructible.h> @@ -35,6 +34,7 @@ #include <__ranges/single_view.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/maybe_const.h> #include <__utility/forward.h> #include <__utility/move.h> #include <type_traits> @@ -45,7 +45,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -458,7 +458,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/non_propagating_cache.h b/libcxx/include/__ranges/non_propagating_cache.h index 7255705256d7..d50c577fc30f 100644 --- a/libcxx/include/__ranges/non_propagating_cache.h +++ b/libcxx/include/__ranges/non_propagating_cache.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H #define _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H @@ -14,7 +15,6 @@ #include <__iterator/iterator_traits.h> // iter_reference_t #include <__memory/addressof.h> #include <__utility/forward.h> -#include <concepts> // constructible_from #include <optional> #include <type_traits> @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { // __non_propagating_cache is a helper type that allows storing an optional value in it, @@ -107,7 +107,7 @@ namespace ranges { struct __empty_cache { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/owning_view.h b/libcxx/include/__ranges/owning_view.h index ac1ef08fecc2..e150f6d9f248 100644 --- a/libcxx/include/__ranges/owning_view.h +++ b/libcxx/include/__ranges/owning_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_OWNING_VIEW_H #define _LIBCPP___RANGES_OWNING_VIEW_H @@ -28,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<range _Rp> @@ -68,13 +69,14 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr auto data() const requires contiguous_range<const _Rp> { return ranges::data(__r_); } }; + _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(owning_view); template<class _Tp> inline constexpr bool enable_borrowed_range<owning_view<_Tp>> = enable_borrowed_range<_Tp>; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/range_adaptor.h b/libcxx/include/__ranges/range_adaptor.h index b65233b56359..37e48179e378 100644 --- a/libcxx/include/__ranges/range_adaptor.h +++ b/libcxx/include/__ranges/range_adaptor.h @@ -10,13 +10,16 @@ #ifndef _LIBCPP___RANGES_RANGE_ADAPTOR_H #define _LIBCPP___RANGES_RANGE_ADAPTOR_H +#include <__concepts/constructible.h> +#include <__concepts/derived_from.h> +#include <__concepts/invocable.h> +#include <__concepts/same_as.h> #include <__config> #include <__functional/compose.h> #include <__functional/invoke.h> #include <__ranges/concepts.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 // CRTP base that one can derive from in order to be considered a range adaptor closure // by the library. When deriving from this class, a pipe operator will be provided to @@ -41,6 +44,7 @@ template <class _Fn> struct __range_adaptor_closure_t : _Fn, __range_adaptor_closure<__range_adaptor_closure_t<_Fn>> { constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { } }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__range_adaptor_closure_t); template <class _Tp> concept _RangeAdaptorClosure = derived_from<remove_cvref_t<_Tp>, __range_adaptor_closure<remove_cvref_t<_Tp>>>; @@ -66,7 +70,7 @@ struct __range_adaptor_closure { { return __range_adaptor_closure_t(std::__compose(std::forward<_OtherClosure>(__c2), std::forward<_Closure>(__c1))); } }; -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/rbegin.h b/libcxx/include/__ranges/rbegin.h index 9291359fdf3b..26b47321de93 100644 --- a/libcxx/include/__ranges/rbegin.h +++ b/libcxx/include/__ranges/rbegin.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_RBEGIN_H #define _LIBCPP___RANGES_RBEGIN_H @@ -25,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 // [ranges.access.rbegin] @@ -123,7 +124,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/ref_view.h b/libcxx/include/__ranges/ref_view.h index e69c715fb9e4..1e5f7466f321 100644 --- a/libcxx/include/__ranges/ref_view.h +++ b/libcxx/include/__ranges/ref_view.h @@ -6,9 +6,12 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_REF_VIEW_H #define _LIBCPP___RANGES_REF_VIEW_H +#include <__concepts/convertible_to.h> +#include <__concepts/different_from.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> @@ -22,7 +25,6 @@ #include <__ranges/size.h> #include <__ranges/view_interface.h> #include <__utility/forward.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -31,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<range _Range> @@ -45,7 +47,7 @@ namespace ranges { public: template<class _Tp> requires __different_from<_Tp, ref_view> && - convertible_to<_Tp, _Range&> && requires { __fun(declval<_Tp>()); } + convertible_to<_Tp, _Range&> && requires { __fun(std::declval<_Tp>()); } _LIBCPP_HIDE_FROM_ABI constexpr ref_view(_Tp&& __t) : __range_(std::addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) @@ -79,7 +81,7 @@ public: inline constexpr bool enable_borrowed_range<ref_view<_Tp>> = true; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/rend.h b/libcxx/include/__ranges/rend.h index e507b2587277..d2987e9fa8c3 100644 --- a/libcxx/include/__ranges/rend.h +++ b/libcxx/include/__ranges/rend.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_REND_H #define _LIBCPP___RANGES_REND_H @@ -26,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 // [range.access.rend] @@ -127,7 +128,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/reverse_view.h b/libcxx/include/__ranges/reverse_view.h index b1df8fbc337b..d7b137805448 100644 --- a/libcxx/include/__ranges/reverse_view.h +++ b/libcxx/include/__ranges/reverse_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_REVERSE_VIEW_H #define _LIBCPP___RANGES_REVERSE_VIEW_H @@ -33,7 +34,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<view _View> @@ -183,7 +184,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/single_view.h b/libcxx/include/__ranges/single_view.h index 98ebe5f3839f..5c4b91869c1c 100644 --- a/libcxx/include/__ranges/single_view.h +++ b/libcxx/include/__ranges/single_view.h @@ -6,9 +6,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_SINGLE_VIEW_H #define _LIBCPP___RANGES_SINGLE_VIEW_H +#include <__concepts/constructible.h> #include <__config> #include <__ranges/copyable_box.h> #include <__ranges/range_adaptor.h> @@ -16,7 +18,6 @@ #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -25,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<copy_constructible _Tp> @@ -94,7 +95,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h index 32ca4b854bc3..0ac8d63063d4 100644 --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -6,17 +6,23 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_SIZE_H #define _LIBCPP___RANGES_SIZE_H +#include <__concepts/arithmetic.h> #include <__concepts/class_or_enum.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/make_signed.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> -#include <concepts> -#include <type_traits> +#include <__utility/declval.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -65,7 +71,7 @@ concept __difference = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { { ranges::begin(__t) } -> forward_iterator; - { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>; + { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(std::declval<_Tp>()))>; }; struct __fn { diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h new file mode 100644 index 000000000000..9758ee935f29 --- /dev/null +++ b/libcxx/include/__ranges/split_view.h @@ -0,0 +1,232 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_SPLIT_VIEW_H +#define _LIBCPP___RANGES_SPLIT_VIEW_H + +#include <__algorithm/ranges_search.h> +#include <__concepts/constructible.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/ranges_operations.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/empty.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/single_view.h> +#include <__ranges/subrange.h> +#include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +template <class _View, class _Pattern> +struct __split_view_iterator; + +template <class _View, class _Pattern> +struct __split_view_sentinel; + +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +class split_view : public view_interface<split_view<_View, _Pattern>> { +private: + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); + using _Cache = __non_propagating_cache<subrange<iterator_t<_View>>>; + _Cache __cached_begin_ = _Cache(); + + template <class, class> + friend struct __split_view_iterator; + + template <class, class> + friend struct __split_view_sentinel; + + using __iterator = __split_view_iterator<_View, _Pattern>; + using __sentinel = __split_view_sentinel<_View, _Pattern>; + + _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { + auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); + if (__begin != ranges::end(__base_) && ranges::empty(__pattern_)) { + ++__begin; + ++__end; + } + return {__begin, __end}; + } + +public: + _LIBCPP_HIDE_FROM_ABI split_view() + requires default_initializable<_View> && default_initializable<_Pattern> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern) + : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} + + template <forward_range _Range> + requires constructible_from<_View, views::all_t<_Range>> && + constructible_from<_Pattern, single_view<range_value_t<_Range>>> + _LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem) + : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { + if (!__cached_begin_.__has_value()) { + __cached_begin_.__emplace(__find_next(ranges::begin(__base_))); + } + return {*this, ranges::begin(__base_), *__cached_begin_}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() { + if constexpr (common_range<_View>) { + return __iterator{*this, ranges::end(__base_), {}}; + } else { + return __sentinel{*this}; + } + } +}; + +template <class _Range, class _Pattern> +split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>; + +template <forward_range _Range> +split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; + +template <class _View, class _Pattern> +struct __split_view_iterator { +private: + split_view<_View, _Pattern>* __parent_ = nullptr; + _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); + _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); + bool __trailing_empty_ = false; + + template <class, class> + friend struct __split_view_sentinel; + +public: + using iterator_concept = forward_iterator_tag; + using iterator_category = input_iterator_tag; + using value_type = subrange<iterator_t<_View>>; + using difference_type = range_difference_t<_View>; + + _LIBCPP_HIDE_FROM_ABI __split_view_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator( + split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) + : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; } + + _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } + + _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator& operator++() { + __cur_ = __next_.begin(); + if (__cur_ != ranges::end(__parent_->__base_)) { + __cur_ = __next_.end(); + if (__cur_ == ranges::end(__parent_->__base_)) { + __trailing_empty_ = true; + __next_ = {__cur_, __cur_}; + } else { + __next_ = __parent_->__find_next(__cur_); + } + } else { + __trailing_empty_ = false; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator operator++(int) { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __split_view_iterator& __x, const __split_view_iterator& __y) { + return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; + } +}; + +template <class _View, class _Pattern> +struct __split_view_sentinel { +private: + _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); + + _LIBCPP_HIDE_FROM_ABI static constexpr bool + __equals(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; + } + +public: + _LIBCPP_HIDE_FROM_ABI __split_view_sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __split_view_sentinel(split_view<_View, _Pattern>& __parent) + : __end_(ranges::end(__parent.__base_)) {} + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + return __equals(__x, __y); + } +}; + +namespace views { +namespace __split_view { +struct __fn : __range_adaptor_closure<__fn> { + // clang-format off + template <class _Range, class _Pattern> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const + noexcept(noexcept(split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) + -> decltype( split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) + { return split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); } + // clang-format on + + template <class _Pattern> + requires constructible_from<decay_t<_Pattern>, _Pattern> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pattern&& __pattern) const + noexcept(is_nothrow_constructible_v<decay_t<_Pattern>, _Pattern>) { + return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pattern>(__pattern))); + } +}; +} // namespace __split_view + +inline namespace __cpo { +inline constexpr auto split = __split_view::__fn{}; +} // namespace __cpo +} // namespace views + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_SPLIT_VIEW_H diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h index 7e42da6ce7f9..2d9e4cc7e55e 100644 --- a/libcxx/include/__ranges/subrange.h +++ b/libcxx/include/__ranges/subrange.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_SUBRANGE_H #define _LIBCPP___RANGES_SUBRANGE_H @@ -16,6 +17,8 @@ #include <__concepts/derived_from.h> #include <__concepts/different_from.h> #include <__config> +#include <__fwd/get.h> +#include <__fwd/subrange.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> @@ -26,9 +29,18 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple> +#include <__tuple_dir/pair_like.h> +#include <__tuple_dir/tuple_element.h> +#include <__tuple_dir/tuple_size.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_pointer.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -36,7 +48,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { template<class _From, class _To> @@ -49,17 +61,6 @@ namespace ranges { convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>; - template<class _Tp> - concept __pair_like = - !is_reference_v<_Tp> && requires(_Tp __t) { - typename tuple_size<_Tp>::type; // Ensures `tuple_size<T>` is complete. - requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>; - typename tuple_element_t<0, remove_const_t<_Tp>>; - typename tuple_element_t<1, remove_const_t<_Tp>>; - { std::get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>; - { std::get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>; - }; - template<class _Pair, class _Iter, class _Sent> concept __pair_like_convertible_from = !range<_Pair> && __pair_like<_Pair> && @@ -67,8 +68,6 @@ namespace ranges { __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>; - enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; - template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized @@ -285,7 +284,7 @@ struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { using type = _Sp; }; -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h index 11d5c9fc36bc..bea3862cd7c8 100644 --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -6,11 +6,15 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_TAKE_VIEW_H #define _LIBCPP___RANGES_TAKE_VIEW_H #include <__algorithm/min.h> #include <__algorithm/ranges_min.h> +#include <__assert> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> #include <__config> #include <__functional/bind_back.h> #include <__fwd/span.h> @@ -30,10 +34,10 @@ #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/maybe_const.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <concepts> #include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -45,7 +49,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -60,9 +64,10 @@ public: _LIBCPP_HIDE_FROM_ABI take_view() requires default_initializable<_View> = default; - _LIBCPP_HIDE_FROM_ABI - constexpr take_view(_View __base, range_difference_t<_View> __count) - : __base_(std::move(__base)), __count_(__count) {} + _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count) + : __base_(std::move(__base)), __count_(__count) { + _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero"); + } _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } @@ -225,6 +230,7 @@ struct __passthrough_type<basic_string_view<_CharT, _Traits>> { }; template <class _Iter, class _Sent, subrange_kind _Kind> + requires requires{typename subrange<_Iter>;} struct __passthrough_type<subrange<_Iter, _Sent, _Kind>> { using type = subrange<_Iter>; }; @@ -328,7 +334,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h new file mode 100644 index 000000000000..59c0a4f82889 --- /dev/null +++ b/libcxx/include/__ranges/take_while_view.h @@ -0,0 +1,183 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_TAKE_WHILE_VIEW_H +#define _LIBCPP___RANGES_TAKE_WHILE_VIEW_H + +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/copyable_box.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/maybe_const.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { + +// The spec uses the unnamed requirement inside the `begin` and `end` member functions: +// constexpr auto begin() const +// requires range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>> +// However, due to a clang-14 and clang-15 bug, the above produces a hard error when `const V` is not a range. +// The workaround is to create a named concept and use the concept instead. +// As of take_while_view is implemented, the clang-trunk has already fixed the bug. +// It is OK to remove the workaround once our CI no longer uses clang-14, clang-15 based compilers, +// because we don't actually expect a lot of vendors to ship a new libc++ with an old clang. +template <class _View, class _Pred> +concept __take_while_const_is_range = + range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>; + +template <class, class, bool> +class __take_while_view_sentinel; + +template <view _View, class _Pred> + requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> +class take_while_view : public view_interface<take_while_view<_View, _Pred>> { + template <class, class, bool> + friend class __take_while_view_sentinel; + + template <bool _Const> + using __sentinel = __take_while_view_sentinel<_View, _Pred, _Const>; + + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + +public: + _LIBCPP_HIDE_FROM_ABI take_while_view() + requires default_initializable<_View> && default_initializable<_Pred> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr take_while_view(_View __base, _Pred __pred) + : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& + requires copy_constructible<_View> + { + return __base_; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() + requires(!__simple_view<_View>) + { + return ranges::begin(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const + requires __take_while_const_is_range<_View, _Pred> + { + return ranges::begin(__base_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() + requires(!__simple_view<_View>) + { + return __sentinel</*_Const=*/false>(ranges::end(__base_), std::addressof(*__pred_)); + } + + _LIBCPP_HIDE_FROM_ABI constexpr auto end() const + requires __take_while_const_is_range<_View, _Pred> + { + return __sentinel</*_Const=*/true>(ranges::end(__base_), std::addressof(*__pred_)); + } +}; + +template <class _Range, class _Pred> +take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>; + +template <class _View, class _Pred, bool _Const> +class __take_while_view_sentinel { + using _Base = __maybe_const<_Const, _View>; + + sentinel_t<_Base> __end_ = sentinel_t<_Base>(); + const _Pred* __pred_ = nullptr; + + template <class, class, bool> + friend class __take_while_view_sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI __take_while_view_sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __take_while_view_sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + : __end_(std::move(__end)), __pred_(__pred) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __take_while_view_sentinel(__take_while_view_sentinel<_View, _Pred, !_Const> __s) + requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> + : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {} + + _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const iterator_t<_Base>& __x, const __take_while_view_sentinel& __y) { + return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); + } + + template <bool _OtherConst = !_Const> + requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __take_while_view_sentinel& __y) { + return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); + } +}; + +namespace views { +namespace __take_while { + +struct __fn { + template <class _Range, class _Pred> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const + noexcept(noexcept(/**/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) + -> decltype(/*--*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) { + return /*-------------*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)); + } + + template <class _Pred> + requires constructible_from<decay_t<_Pred>, _Pred> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const + noexcept(is_nothrow_constructible_v<decay_t<_Pred>, _Pred>) { + return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred))); + } +}; + +} // namespace __take_while + +inline namespace __cpo { +inline constexpr auto take_while = __take_while::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_TAKE_WHILE_VIEW_H diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h index c5a7128c366b..66d9e80e6e61 100644 --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_TRANSFORM_VIEW_H #define _LIBCPP___RANGES_TRANSFORM_VIEW_H @@ -30,6 +31,7 @@ #include <__ranges/range_adaptor.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/maybe_const.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> @@ -41,7 +43,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -55,11 +57,31 @@ concept __transform_view_constraints = regular_invocable<_Fn&, range_reference_t<_View>> && __can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>; +template <input_range _View, copy_constructible _Function, bool _IsConst> + requires __transform_view_constraints<_View, _Function> +class __transform_view_iterator; + +template <input_range _View, copy_constructible _Function, bool _IsConst> + requires __transform_view_constraints<_View, _Function> +class __transform_view_sentinel; + template<input_range _View, copy_constructible _Fn> requires __transform_view_constraints<_View, _Fn> class transform_view : public view_interface<transform_view<_View, _Fn>> { - template<bool> class __iterator; - template<bool> class __sentinel; + + template <bool _IsConst> + using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; + + template <bool _IsConst> + using __sentinel = __transform_view_sentinel<_View, _Fn, _IsConst>; + + template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_iterator; + + template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_sentinel; _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); @@ -154,22 +176,23 @@ struct __transform_view_iterator_category_base<_View, _Fn> { >; }; -template<input_range _View, copy_constructible _Fn> +template<input_range _View, copy_constructible _Fn, bool _Const> requires __transform_view_constraints<_View, _Fn> -template<bool _Const> -class transform_view<_View, _Fn>::__iterator +class __transform_view_iterator : public __transform_view_iterator_category_base<_View, _Fn> { - using _Parent = __maybe_const<_Const, transform_view>; + using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; using _Base = __maybe_const<_Const, _View>; _Parent *__parent_ = nullptr; - template<bool> - friend class transform_view<_View, _Fn>::__iterator; + template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_iterator; - template<bool> - friend class transform_view<_View, _Fn>::__sentinel; + template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_sentinel; public: iterator_t<_Base> __current_ = iterator_t<_Base>(); @@ -179,17 +202,17 @@ public: using difference_type = range_difference_t<_Base>; _LIBCPP_HIDE_FROM_ABI - __iterator() requires default_initializable<iterator_t<_Base>> = default; + __transform_view_iterator() requires default_initializable<iterator_t<_Base>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current) + constexpr __transform_view_iterator(_Parent& __parent, iterator_t<_Base> __current) : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} - // Note: `__i` should always be `__iterator<false>`, but directly using - // `__iterator<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__transform_view_iterator<false>`, but directly using + // `__transform_view_iterator<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(__iterator<!_Const> __i) + constexpr __transform_view_iterator(__transform_view_iterator<_View, _Fn, !_Const> __i) requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} @@ -211,7 +234,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { + constexpr __transform_view_iterator& operator++() { ++__current_; return *this; } @@ -220,7 +243,7 @@ public: constexpr void operator++(int) { ++__current_; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) + constexpr __transform_view_iterator operator++(int) requires forward_range<_Base> { auto __tmp = *this; @@ -229,7 +252,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() + constexpr __transform_view_iterator& operator--() requires bidirectional_range<_Base> { --__current_; @@ -237,7 +260,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) + constexpr __transform_view_iterator operator--(int) requires bidirectional_range<_Base> { auto __tmp = *this; @@ -246,7 +269,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator+=(difference_type __n) + constexpr __transform_view_iterator& operator+=(difference_type __n) requires random_access_range<_Base> { __current_ += __n; @@ -254,7 +277,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator-=(difference_type __n) + constexpr __transform_view_iterator& operator-=(difference_type __n) requires random_access_range<_Base> { __current_ -= __n; @@ -270,77 +293,77 @@ public: } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator==(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires equality_comparable<iterator_t<_Base>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator<(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires random_access_range<_Base> { return __x.__current_ < __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires random_access_range<_Base> { return __x.__current_ > __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator<=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires random_access_range<_Base> { return __x.__current_ <= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator>=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires random_access_range<_Base> { return __x.__current_ >= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + friend constexpr auto operator<=>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> { return __x.__current_ <=> __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(__iterator __i, difference_type __n) + friend constexpr __transform_view_iterator operator+(__transform_view_iterator __i, difference_type __n) requires random_access_range<_Base> { - return __iterator{*__i.__parent_, __i.__current_ + __n}; + return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(difference_type __n, __iterator __i) + friend constexpr __transform_view_iterator operator+(difference_type __n, __transform_view_iterator __i) requires random_access_range<_Base> { - return __iterator{*__i.__parent_, __i.__current_ + __n}; + return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator-(__iterator __i, difference_type __n) + friend constexpr __transform_view_iterator operator-(__transform_view_iterator __i, difference_type __n) requires random_access_range<_Base> { - return __iterator{*__i.__parent_, __i.__current_ - __n}; + return __transform_view_iterator{*__i.__parent_, __i.__current_ - __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + friend constexpr difference_type operator-(const __transform_view_iterator& __x, const __transform_view_iterator& __y) requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> { return __x.__current_ - __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __iterator& __i) + friend constexpr decltype(auto) iter_move(const __transform_view_iterator& __i) noexcept(noexcept(*__i)) { if constexpr (is_lvalue_reference_v<decltype(*__i)>) @@ -350,33 +373,37 @@ public: } }; -template<input_range _View, copy_constructible _Fn> +template<input_range _View, copy_constructible _Fn, bool _Const> requires __transform_view_constraints<_View, _Fn> -template<bool _Const> -class transform_view<_View, _Fn>::__sentinel { - using _Parent = __maybe_const<_Const, transform_view>; +class __transform_view_sentinel { + using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; using _Base = __maybe_const<_Const, _View>; + template <bool _IsConst> + using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; + sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template<bool> - friend class transform_view<_View, _Fn>::__iterator; + template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_iterator; - template<bool> - friend class transform_view<_View, _Fn>::__sentinel; + template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> + requires __transform_view_constraints<_ViewType, _FunctionType> + friend class __transform_view_sentinel; public: _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; + __transform_view_sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {} + constexpr explicit __transform_view_sentinel(sentinel_t<_Base> __end) : __end_(__end) {} - // Note: `__i` should always be `__sentinel<false>`, but directly using - // `__sentinel<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__transform_view_sentinel<false>`, but directly using + // `__transform_view_sentinel<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __sentinel(__sentinel<!_Const> __i) + constexpr __transform_view_sentinel(__transform_view_sentinel<_View, _Fn, !_Const> __i) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__i.__end_)) {} @@ -386,7 +413,7 @@ public: template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { return __x.__current_ == __y.__end_; } @@ -394,7 +421,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { return __x.__current_ - __y.__end_; } @@ -402,7 +429,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { + operator-(const __transform_view_sentinel& __x, const __iterator<_OtherConst>& __y) { return __x.__end_ - __y.__current_; } }; @@ -433,7 +460,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h index 4b36e02f7d6b..5581eb9c732a 100644 --- a/libcxx/include/__ranges/view_interface.h +++ b/libcxx/include/__ranges/view_interface.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H #define _LIBCPP___RANGES_VIEW_INTERFACE_H @@ -20,7 +21,9 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/empty.h> -#include <type_traits> +#include <__type_traits/is_class.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -99,7 +102,7 @@ public: constexpr auto size() requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> { - return ranges::end(__derived()) - ranges::begin(__derived()); + return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); } template<class _D2 = _Derived> @@ -107,7 +110,7 @@ public: constexpr auto size() const requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> { - return ranges::end(__derived()) - ranges::begin(__derived()); + return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); } template<class _D2 = _Derived> @@ -167,7 +170,7 @@ public: } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/views.h b/libcxx/include/__ranges/views.h index 8cc5ba3d2aca..d40c64ad8c02 100644 --- a/libcxx/include/__ranges/views.h +++ b/libcxx/include/__ranges/views.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 17 namespace ranges { @@ -28,7 +28,7 @@ namespace views { } namespace views = ranges::views; -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h index a8035bc79e12..5624726e13ee 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -6,6 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef _LIBCPP___RANGES_ZIP_VIEW_H #define _LIBCPP___RANGES_ZIP_VIEW_H @@ -44,7 +45,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#if _LIBCPP_STD_VER > 20 namespace ranges { @@ -402,15 +403,15 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr auto iter_move(const __iterator& __i) noexcept( - (noexcept(ranges::iter_move(declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) && + (noexcept(ranges::iter_move(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) && (is_nothrow_move_constructible_v<range_rvalue_reference_t<__maybe_const<_Const, _Views>>> && ...)) { return ranges::__tuple_transform(ranges::iter_move, __i.__current_); } _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( - (noexcept(ranges::iter_swap(declval<const iterator_t<__maybe_const<_Const, _Views>>&>(), - declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && + (noexcept(ranges::iter_swap(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>(), + std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...)) requires(indirectly_swappable<iterator_t<__maybe_const<_Const, _Views>>> && ...) { ranges::__tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); @@ -502,7 +503,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +#endif // _LIBCPP_STD_VER > 20 _LIBCPP_END_NAMESPACE_STD |
