diff options
author | mikhnenko <mikhnenko@yandex-team.com> | 2023-10-14 13:00:57 +0300 |
---|---|---|
committer | mikhnenko <mikhnenko@yandex-team.com> | 2023-10-14 13:22:30 +0300 |
commit | 4371a757495f375ca7c5b1730f4e9f741a71ec40 (patch) | |
tree | be8f3405e7b0534d29bfb8eec493c0dbe108adc5 /contrib/libs/cxxsupp/libcxx/include/__ranges | |
parent | ecb10029a72bb21f92858ff3c0d76c8f255cf4ba (diff) | |
download | ydb-4371a757495f375ca7c5b1730f4e9f741a71ec40.tar.gz |
Update libc++ to 1 May 2022 639b9618f46d75f4dabd2082b3f6ba8433c287bf
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/include/__ranges')
5 files changed, 1371 insertions, 111 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h new file mode 100644 index 0000000000..b040ea57b7 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/filter_view.h @@ -0,0 +1,259 @@ +// -*- 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_FILTER_VIEW_H +#define _LIBCPP___RANGES_FILTER_VIEW_H + +#include <__algorithm/ranges_find_if.h> +#include <__config> +#include <__debug> +#include <__functional/bind_back.h> +#include <__functional/invoke.h> +#include <__functional/reference_wrapper.h> +#include <__iterator/concepts.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/copyable_box.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/view_interface.h> +#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) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +namespace ranges { + 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>> { + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + + // We cache the result of begin() to allow providing an amortized O(1) begin() whenever + // the underlying range is at least a forward_range. + 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(); + + class __iterator; + class __sentinel; + + public: + _LIBCPP_HIDE_FROM_ABI + filter_view() requires default_initializable<_View> && default_initializable<_Pred> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr filter_view(_View __base, _Pred __pred) + : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) + { } + + template<class _Vp = _View> + _LIBCPP_HIDE_FROM_ABI + constexpr _View base() const& requires copy_constructible<_Vp> { return __base_; } + _LIBCPP_HIDE_FROM_ABI + constexpr _View base() && { return std::move(__base_); } + + _LIBCPP_HIDE_FROM_ABI + constexpr _Pred const& pred() const { return *__pred_; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator begin() { + _LIBCPP_ASSERT(__pred_.__has_value(), "Trying to call begin() on a filter_view that does not have a valid predicate."); + if constexpr (_UseCache) { + if (!__cached_begin_.__has_value()) { + __cached_begin_.__emplace(ranges::find_if(__base_, std::ref(*__pred_))); + } + return {*this, *__cached_begin_}; + } else { + return {*this, ranges::find_if(__base_, std::ref(*__pred_))}; + } + } + + _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 _Pred> + filter_view(_Range&&, _Pred) -> filter_view<views::all_t<_Range>, _Pred>; + + template<class _View> + struct __filter_iterator_category { }; + + template<forward_range _View> + struct __filter_iterator_category<_View> { + using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category; + using iterator_category = + _If<derived_from<_Cat, bidirectional_iterator_tag>, bidirectional_iterator_tag, + _If<derived_from<_Cat, forward_iterator_tag>, forward_iterator_tag, + /* else */ _Cat + >>; + }; + + 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> { + public: + _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>(); + _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr; + + using iterator_concept = + _If<bidirectional_range<_View>, bidirectional_iterator_tag, + _If<forward_range<_View>, forward_iterator_tag, + /* else */ input_iterator_tag + >>; + // using iterator_category = inherited; + using value_type = range_value_t<_View>; + using difference_type = range_difference_t<_View>; + + _LIBCPP_HIDE_FROM_ABI + __iterator() requires default_initializable<iterator_t<_View>> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator(filter_view& __parent, iterator_t<_View> __current) + : __current_(std::move(__current)), __parent_(std::addressof(__parent)) + { } + + _LIBCPP_HIDE_FROM_ABI + constexpr iterator_t<_View> const& base() const& noexcept { return __current_; } + _LIBCPP_HIDE_FROM_ABI + constexpr iterator_t<_View> base() && { return std::move(__current_); } + + _LIBCPP_HIDE_FROM_ABI + constexpr range_reference_t<_View> operator*() const { return *__current_; } + _LIBCPP_HIDE_FROM_ABI + constexpr iterator_t<_View> operator->() const + requires __has_arrow<iterator_t<_View>> && copyable<iterator_t<_View>> + { + return __current_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator++() { + __current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_), + std::ref(*__parent_->__pred_)); + return *this; + } + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator++(int) requires forward_range<_View> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __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> { + auto tmp = *this; + --*this; + return tmp; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(__iterator const& __x, __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) + 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) + noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) + requires indirectly_swappable<iterator_t<_View>> + { + return ranges::iter_swap(__x.__current_, __y.__current_); + } + }; + + template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> + requires view<_View> && is_object_v<_Pred> + class filter_view<_View, _Pred>::__sentinel { + public: + sentinel_t<_View> __end_ = sentinel_t<_View>(); + + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __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) { + return __x.__current_ == __y.__end_; + } + }; + +namespace views { +namespace __filter { + struct __fn { + template<class _Range, class _Pred> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Pred&& __pred) const + noexcept(noexcept(filter_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) + -> decltype( filter_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) + { return filter_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 __filter + +inline namespace __cpo { + inline constexpr auto filter = __filter::__fn{}; +} // namespace __cpo +} // namespace views + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_FILTER_VIEW_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h index 1a1dfad1d2..6c16b68268 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/join_view.h @@ -9,17 +9,22 @@ #ifndef _LIBCPP___RANGES_JOIN_VIEW_H #define _LIBCPP___RANGES_JOIN_VIEW_H +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> #include <__config> #include <__iterator/concepts.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> #include <__ranges/non_propagating_cache.h> -#include <__ranges/ref_view.h> -#include <__ranges/subrange.h> +#include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> -#include <__utility/declval.h> #include <__utility/forward.h> #include <optional> #include <type_traits> @@ -45,7 +50,8 @@ namespace ranges { using _InnerC = typename iterator_traits<iterator_t<range_reference_t<_View>>>::iterator_category; using iterator_category = _If< - derived_from<_OuterC, bidirectional_iterator_tag> && derived_from<_InnerC, bidirectional_iterator_tag>, + derived_from<_OuterC, bidirectional_iterator_tag> && derived_from<_InnerC, bidirectional_iterator_tag> && + common_range<range_reference_t<_View>>, bidirectional_iterator_tag, _If< derived_from<_OuterC, forward_iterator_tag> && derived_from<_InnerC, forward_iterator_tag>, @@ -204,7 +210,8 @@ namespace ranges { 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< __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>>, @@ -339,6 +346,21 @@ 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> { + template<class _Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range) const + noexcept(noexcept(join_view<all_t<_Range&&>>(std::forward<_Range>(__range)))) + -> decltype( join_view<all_t<_Range&&>>(std::forward<_Range>(__range))) + { return join_view<all_t<_Range&&>>(std::forward<_Range>(__range)); } +}; +} // namespace __join_view +inline namespace __cpo { + inline constexpr auto join = __join_view::__fn{}; +} // namespace __cpo +} // namespace views } // namespace ranges #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/lazy_split_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/lazy_split_view.h new file mode 100644 index 0000000000..68617c48f8 --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/lazy_split_view.h @@ -0,0 +1,466 @@ +// -*- 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_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> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/default_sentinel.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/indirectly_comparable.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.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 <__utility/forward.h> +#include <__utility/move.h> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +namespace ranges { + +template <auto> struct __require_constant; + +template <class _Range> +concept __tiny_range = + sized_range<_Range> && + requires { typename __require_constant<remove_reference_t<_Range>::size()>; } && + (remove_reference_t<_Range>::size() <= 1); + +template <input_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> && + (forward_range<_View> || __tiny_range<_Pattern>) +class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>> { + + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + _LIBCPP_NO_UNIQUE_ADDRESS _Pattern __pattern_ = _Pattern(); + + using _MaybeCurrent = _If<!forward_range<_View>, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); + + template <bool> struct __outer_iterator; + template <bool> struct __inner_iterator; + +public: + _LIBCPP_HIDE_FROM_ABI + lazy_split_view() + requires default_initializable<_View> && default_initializable<_Pattern> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr lazy_split_view(_View __base, _Pattern __pattern) + : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {} + + template <input_range _Range> + requires constructible_from<_View, views::all_t<_Range>> && + constructible_from<_Pattern, single_view<range_value_t<_Range>>> + _LIBCPP_HIDE_FROM_ABI + constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e) + : __base_(views::all(std::forward<_Range>(__r))) + // TODO(varconst): use `views::single` once it's implemented. + , __pattern_(ranges::single_view(std::move(__e))) {} + + _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() { + if constexpr (forward_range<_View>) { + return __outer_iterator<__simple_view<_View> && __simple_view<_Pattern>>{*this, ranges::begin(__base_)}; + } else { + __current_.__emplace(ranges::begin(__base_)); + return __outer_iterator<false>{*this}; + } + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() const requires forward_range<_View> && forward_range<const _View> { + return __outer_iterator<true>{*this, ranges::begin(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() requires forward_range<_View> && common_range<_View> { + return __outer_iterator<__simple_view<_View> && __simple_view<_Pattern>>{*this, ranges::end(__base_)}; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() const { + if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View>) { + return __outer_iterator<true>{*this, ranges::end(__base_)}; + } else { + return default_sentinel; + } + } + +private: + + template <class> + struct __outer_iterator_category {}; + + template <forward_range _Tp> + struct __outer_iterator_category<_Tp> { + using iterator_category = input_iterator_tag; + }; + + template <bool _Const> + struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> { + private: + template <bool> + friend struct __inner_iterator; + friend __outer_iterator<true>; + + using _Parent = __maybe_const<_Const, lazy_split_view>; + using _Base = __maybe_const<_Const, _View>; + + _Parent* __parent_ = nullptr; + using _MaybeCurrent = _If<forward_range<_View>, iterator_t<_Base>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); + bool __trailing_empty_ = false; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __current() noexcept { + if constexpr (forward_range<_View>) { + return __current_; + } else { + return *__parent_->__current_; + } + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr const auto& __current() const noexcept { + if constexpr (forward_range<_View>) { + return __current_; + } else { + return *__parent_->__current_; + } + } + + // Workaround for the GCC issue that doesn't allow calling `__parent_->__base_` from friend functions (because + // `__base_` is private). + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __parent_base() const noexcept { + return __parent_->__base_; + } + + public: + // using iterator_category = inherited; + using iterator_concept = conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>; + using difference_type = range_difference_t<_Base>; + + struct value_type : view_interface<value_type> { + private: + __outer_iterator __i_ = __outer_iterator(); + + public: + _LIBCPP_HIDE_FROM_ABI + value_type() = default; + _LIBCPP_HIDE_FROM_ABI + constexpr explicit value_type(__outer_iterator __i) + : __i_(std::move(__i)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr __inner_iterator<_Const> begin() const { return __inner_iterator<_Const>{__i_}; } + _LIBCPP_HIDE_FROM_ABI + constexpr default_sentinel_t end() const noexcept { return default_sentinel; } + }; + + _LIBCPP_HIDE_FROM_ABI + __outer_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __outer_iterator(_Parent& __parent) + requires (!forward_range<_Base>) + : __parent_(std::addressof(__parent)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current) + requires forward_range<_Base> + : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr __outer_iterator(__outer_iterator<!_Const> __i) + requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> + : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr value_type operator*() const { return value_type{*this}; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __outer_iterator& operator++() { + const auto __end = ranges::end(__parent_->__base_); + if (__current() == __end) { + __trailing_empty_ = false; + return *this; + } + + const auto [__pbegin, __pend] = ranges::subrange{__parent_->__pattern_}; + if (__pbegin == __pend) { + // Empty pattern: split on every element in the input range + ++__current(); + + } else if constexpr (__tiny_range<_Pattern>) { + // One-element pattern: we can use `ranges::find`. + __current() = ranges::find(std::move(__current()), __end, *__pbegin); + if (__current() != __end) { + // Make sure we point to after the separator we just found. + ++__current(); + if (__current() == __end) + __trailing_empty_ = true; + } + + } else { + // General case for n-element pattern. + do { + const auto [__b, __p] = ranges::mismatch(__current(), __end, __pbegin, __pend); + if (__p == __pend) { + __current() = __b; + if (__current() == __end) { + __trailing_empty_ = true; + } + break; // The pattern matched; skip it. + } + } while (++__current() != __end); + } + + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator++(int) { + if constexpr (forward_range<_Base>) { + auto __tmp = *this; + ++*this; + return __tmp; + + } else { + ++*this; + } + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __outer_iterator& __x, const __outer_iterator& __y) + requires forward_range<_Base> { + return __x.__current_ == __y.__current_ && __x.__trailing_empty_ == __y.__trailing_empty_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) { + _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); + return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; + } + }; + + template <class> + struct __inner_iterator_category {}; + + template <forward_range _Tp> + struct __inner_iterator_category<_Tp> { + using iterator_category = _If< + derived_from<typename iterator_traits<iterator_t<_Tp>>::iterator_category, forward_iterator_tag>, + forward_iterator_tag, + typename iterator_traits<iterator_t<_Tp>>::iterator_category + >; + }; + + template <bool _Const> + struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> { + private: + using _Base = __maybe_const<_Const, _View>; + // Workaround for a GCC issue. + static constexpr bool _OuterConst = _Const; + __outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>(); + bool __incremented_ = false; + + // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from + // free functions that are friends of `inner-iterator`. + + _LIBCPP_HIDE_FROM_ABI + constexpr bool __is_done() const { + _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); + + auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; + auto __end = ranges::end(__i_.__parent_->__base_); + + if constexpr (__tiny_range<_Pattern>) { + const auto& __cur = __i_.__current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return __incremented_; + + return *__cur == *__pcur; + + } else { + auto __cur = __i_.__current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return __incremented_; + + do { + if (*__cur != *__pcur) + return false; + if (++__pcur == __pend) + return true; + } while (++__cur != __end); + + return false; + } + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __outer_current() noexcept { + return __i_.__current(); + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr const auto& __outer_current() const noexcept { + return __i_.__current(); + } + + public: + // using iterator_category = inherited; + using iterator_concept = typename __outer_iterator<_Const>::iterator_concept; + using value_type = range_value_t<_Base>; + using difference_type = range_difference_t<_Base>; + + _LIBCPP_HIDE_FROM_ABI + __inner_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) + : __i_(std::move(__i)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); } + _LIBCPP_HIDE_FROM_ABI + constexpr iterator_t<_Base> base() && + requires forward_range<_View> { return std::move(__i_.__current()); } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator*() const { return *__i_.__current(); } + + _LIBCPP_HIDE_FROM_ABI + constexpr __inner_iterator& operator++() { + __incremented_ = true; + + if constexpr (!forward_range<_Base>) { + if constexpr (_Pattern::size() == 0) { + return *this; + } + } + + ++__i_.__current(); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator++(int) { + if constexpr (forward_range<_Base>) { + auto __tmp = *this; + ++*this; + return __tmp; + + } else { + ++*this; + } + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __inner_iterator& __x, const __inner_iterator& __y) + requires forward_range<_Base> { + return __x.__outer_current() == __y.__outer_current(); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __inner_iterator& __x, default_sentinel_t) { + return __x.__is_done(); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr decltype(auto) iter_move(const __inner_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) { + return ranges::iter_move(__i.__outer_current()); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr void iter_swap(const __inner_iterator& __x, const __inner_iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x.__outer_current(), __y.__outer_current()))) + requires indirectly_swappable<iterator_t<_Base>> { + ranges::iter_swap(__x.__outer_current(), __y.__outer_current()); + } + }; + +}; + +template <class _Range, class _Pattern> +lazy_split_view(_Range&&, _Pattern&&) -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>; + +template <input_range _Range> +lazy_split_view(_Range&&, range_value_t<_Range>) + -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; + +namespace views { +namespace __lazy_split_view { +struct __fn : __range_adaptor_closure<__fn> { + template <class _Range, class _Pattern> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const + noexcept(noexcept(lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)))) + -> decltype( lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern))) + { return lazy_split_view(std::forward<_Range>(__range), std::forward<_Pattern>(__pattern)); } + + template <class _Pattern> + requires constructible_from<decay_t<_Pattern>, _Pattern> + [[nodiscard]] _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 __lazy_split_view + +inline namespace __cpo { + inline constexpr auto lazy_split = __lazy_split_view::__fn{}; +} // namespace __cpo +} // namespace views + +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_LAZY_SPLIT_VIEW_H diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h index 9602ee1b2a..3ad7810a9c 100644 --- a/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/take_view.h @@ -37,141 +37,143 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) namespace ranges { - template<view _View> - class take_view : public view_interface<take_view<_View>> { - _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - range_difference_t<_View> __count_ = 0; - - template<bool> class __sentinel; - - 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 _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>) { - if constexpr (sized_range<_View>) { - if constexpr (random_access_range<_View>) { - return ranges::begin(__base_); - } else { - using _DifferenceT = range_difference_t<_View>; - auto __size = size(); - return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); - } + +template<view _View> +class take_view : public view_interface<take_view<_View>> { + _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + range_difference_t<_View> __count_ = 0; + + template<bool> class __sentinel; + +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 _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>) { + if constexpr (sized_range<_View>) { + if constexpr (random_access_range<_View>) { + return ranges::begin(__base_); } else { - return counted_iterator(ranges::begin(__base_), __count_); + using _DifferenceT = range_difference_t<_View>; + auto __size = size(); + return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); } + } else { + return counted_iterator(ranges::begin(__base_), __count_); } + } - _LIBCPP_HIDE_FROM_ABI - constexpr auto begin() const requires range<const _View> { - if constexpr (sized_range<const _View>) { - if constexpr (random_access_range<const _View>) { - return ranges::begin(__base_); - } else { - using _DifferenceT = range_difference_t<const _View>; - auto __size = size(); - return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); - } + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() const requires range<const _View> { + if constexpr (sized_range<const _View>) { + if constexpr (random_access_range<const _View>) { + return ranges::begin(__base_); } else { - return counted_iterator(ranges::begin(__base_), __count_); + using _DifferenceT = range_difference_t<const _View>; + auto __size = size(); + return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); } + } else { + return counted_iterator(ranges::begin(__base_), __count_); } + } - _LIBCPP_HIDE_FROM_ABI - constexpr auto end() requires (!__simple_view<_View>) { - if constexpr (sized_range<_View>) { - if constexpr (random_access_range<_View>) { - return ranges::begin(__base_) + size(); - } else { - return default_sentinel; - } + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() requires (!__simple_view<_View>) { + if constexpr (sized_range<_View>) { + if constexpr (random_access_range<_View>) { + return ranges::begin(__base_) + size(); } else { - return __sentinel<false>{ranges::end(__base_)}; + return default_sentinel; } + } else { + return __sentinel<false>{ranges::end(__base_)}; } + } - _LIBCPP_HIDE_FROM_ABI - constexpr auto end() const requires range<const _View> { - if constexpr (sized_range<const _View>) { - if constexpr (random_access_range<const _View>) { - return ranges::begin(__base_) + size(); - } else { - return default_sentinel; - } + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() const requires range<const _View> { + if constexpr (sized_range<const _View>) { + if constexpr (random_access_range<const _View>) { + return ranges::begin(__base_) + size(); } else { - return __sentinel<true>{ranges::end(__base_)}; + return default_sentinel; } + } else { + return __sentinel<true>{ranges::end(__base_)}; } + } - _LIBCPP_HIDE_FROM_ABI - constexpr auto size() requires sized_range<_View> { - auto __n = ranges::size(__base_); - return ranges::min(__n, static_cast<decltype(__n)>(__count_)); - } + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() requires sized_range<_View> { + auto __n = ranges::size(__base_); + return ranges::min(__n, static_cast<decltype(__n)>(__count_)); + } - _LIBCPP_HIDE_FROM_ABI - constexpr auto size() const requires sized_range<const _View> { - auto __n = ranges::size(__base_); - return ranges::min(__n, static_cast<decltype(__n)>(__count_)); - } - }; + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() const requires sized_range<const _View> { + auto __n = ranges::size(__base_); + return ranges::min(__n, static_cast<decltype(__n)>(__count_)); + } +}; - template<view _View> - template<bool _Const> - class take_view<_View>::__sentinel { - using _Base = __maybe_const<_Const, _View>; - template<bool _OtherConst> - using _Iter = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>; - _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); +template<view _View> +template<bool _Const> +class take_view<_View>::__sentinel { + using _Base = __maybe_const<_Const, _View>; + template<bool _OtherConst> + using _Iter = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>; + _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template<bool> - friend class take_view<_View>::__sentinel; + template<bool> + friend class take_view<_View>::__sentinel; public: - _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} - _LIBCPP_HIDE_FROM_ABI - constexpr __sentinel(__sentinel<!_Const> __s) - requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> - : __end_(std::move(__s.__end_)) {} + _LIBCPP_HIDE_FROM_ABI + constexpr __sentinel(__sentinel<!_Const> __s) + requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> + : __end_(std::move(__s.__end_)) {} - _LIBCPP_HIDE_FROM_ABI - constexpr sentinel_t<_Base> base() const { return __end_; } + _LIBCPP_HIDE_FROM_ABI + constexpr sentinel_t<_Base> base() const { return __end_; } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { - return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; - } + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { + return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; + } - 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 _Iter<_Const>& __lhs, const __sentinel& __rhs) { - return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; - } - }; + 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 _Iter<_Const>& __lhs, const __sentinel& __rhs) { + return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; + } +}; + +template<class _Range> +take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>; - template<class _Range> - take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>; +template<class _Tp> +inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>; - template<class _Tp> - inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>; } // namespace ranges #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) diff --git a/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h b/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h new file mode 100644 index 0000000000..560452aa7c --- /dev/null +++ b/contrib/libs/cxxsupp/libcxx/include/__ranges/zip_view.h @@ -0,0 +1,511 @@ +// -*- 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_ZIP_VIEW_H +#define _LIBCPP___RANGES_ZIP_VIEW_H + +#include <__config> + +#include <__algorithm/ranges_min.h> +#include <__compare/three_way_comparable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/equality_comparable.h> +#include <__functional/invoke.h> +#include <__functional/operations.h> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/empty_view.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__utility/forward.h> +#include <__utility/integer_sequence.h> +#include <__utility/move.h> +#include <tuple> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +namespace ranges { + +template <class... _Ranges> +concept __zip_is_common = (sizeof...(_Ranges) == 1 && (common_range<_Ranges> && ...)) || + (!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) || + ((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...)); + +template <typename _Tp, typename _Up> +auto __tuple_or_pair_test() -> pair<_Tp, _Up>; + +template <typename... _Types> + requires(sizeof...(_Types) != 2) +auto __tuple_or_pair_test() -> tuple<_Types...>; + +template <class... _Types> +using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>()); + +template <class _Fun, class _Tuple> +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) { + return std::apply( + [&]<class... _Types>(_Types&&... __elements) { + return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>( + std::invoke(__f, std::forward<_Types>(__elements))...); + }, + std::forward<_Tuple>(__tuple)); +} + +template <class _Fun, class _Tuple> +_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tuple) { + std::apply( + [&]<class... _Types>(_Types&&... __elements) { (std::invoke(__f, std::forward<_Types>(__elements)), ...); }, + std::forward<_Tuple>(__tuple)); +} + +template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices> +_LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair< + invoke_result_t<_Fun&, typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type, + typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...> +__tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, index_sequence<_Indices...>) { + return {std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), + std::get<_Indices>(std::forward<_Tuple2>(__tuple2)))...}; +} + +template <class _Fun, class _Tuple1, class _Tuple2> +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { + return ranges::__tuple_zip_transform(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2), + std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>()); +} + +template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices> +_LIBCPP_HIDE_FROM_ABI constexpr void __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, + index_sequence<_Indices...>) { + (std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), + std::get<_Indices>(std::forward<_Tuple2>(__tuple2))), + ...); +} + +template <class _Fun, class _Tuple1, class _Tuple2> +_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { + return ranges::__tuple_zip_for_each(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2), + std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>()); +} + +template <class _Tuple1, class _Tuple2> +_LIBCPP_HIDE_FROM_ABI constexpr bool __tuple_any_equals(const _Tuple1& __tuple1, const _Tuple2& __tuple2) { + const auto __equals = ranges::__tuple_zip_transform(std::equal_to<>(), __tuple1, __tuple2); + return std::apply([](auto... __bools) { return (__bools || ...); }, __equals); +} + +// abs in cstdlib is not constexpr +// TODO : remove __abs once P0533R9 is implemented. +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __abs(_Tp __t) { + return __t < 0 ? -__t : __t; +} + +template <input_range... _Views> + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +class zip_view : public view_interface<zip_view<_Views...>> { + + _LIBCPP_NO_UNIQUE_ADDRESS tuple<_Views...> __views_; + + template <bool> + class __iterator; + + template <bool> + class __sentinel; + +public: + _LIBCPP_HIDE_FROM_ABI + zip_view() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit zip_view(_Views... __views) : __views_(std::move(__views)...) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() + requires(!(__simple_view<_Views> && ...)) { + return __iterator<false>(ranges::__tuple_transform(ranges::begin, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto begin() const + requires(range<const _Views> && ...) { + return __iterator<true>(ranges::__tuple_transform(ranges::begin, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() + requires(!(__simple_view<_Views> && ...)) { + if constexpr (!__zip_is_common<_Views...>) { + return __sentinel<false>(ranges::__tuple_transform(ranges::end, __views_)); + } else if constexpr ((random_access_range<_Views> && ...)) { + return begin() + iter_difference_t<__iterator<false>>(size()); + } else { + return __iterator<false>(ranges::__tuple_transform(ranges::end, __views_)); + } + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto end() const + requires(range<const _Views> && ...) { + if constexpr (!__zip_is_common<const _Views...>) { + return __sentinel<true>(ranges::__tuple_transform(ranges::end, __views_)); + } else if constexpr ((random_access_range<const _Views> && ...)) { + return begin() + iter_difference_t<__iterator<true>>(size()); + } else { + return __iterator<true>(ranges::__tuple_transform(ranges::end, __views_)); + } + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() + requires(sized_range<_Views> && ...) { + return std::apply( + [](auto... __sizes) { + using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>; + return ranges::min({_CT(__sizes)...}); + }, + ranges::__tuple_transform(ranges::size, __views_)); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto size() const + requires(sized_range<const _Views> && ...) { + return std::apply( + [](auto... __sizes) { + using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>; + return ranges::min({_CT(__sizes)...}); + }, + ranges::__tuple_transform(ranges::size, __views_)); + } +}; + +template <class... _Ranges> +zip_view(_Ranges&&...) -> zip_view<views::all_t<_Ranges>...>; + +template <bool _Const, class... _Views> +concept __zip_all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...); + +template <bool _Const, class... _Views> +concept __zip_all_bidirectional = (bidirectional_range<__maybe_const<_Const, _Views>> && ...); + +template <bool _Const, class... _Views> +concept __zip_all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); + +template <bool _Const, class... _Views> +consteval auto __get_zip_view_iterator_tag() { + if constexpr (__zip_all_random_access<_Const, _Views...>) { + return random_access_iterator_tag(); + } else if constexpr (__zip_all_bidirectional<_Const, _Views...>) { + return bidirectional_iterator_tag(); + } else if constexpr (__zip_all_forward<_Const, _Views...>) { + return forward_iterator_tag(); + } else { + return input_iterator_tag(); + } +} + +template <bool _Const, class... _Views> +struct __zip_view_iterator_category_base {}; + +template <bool _Const, class... _Views> + requires __zip_all_forward<_Const, _Views...> +struct __zip_view_iterator_category_base<_Const, _Views...> { + using iterator_category = input_iterator_tag; +}; + +template <input_range... _Views> + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +template <bool _Const> +class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> { + + __tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __iterator(__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current) + : __current_(std::move(__current)) {} + + template <bool> + friend class zip_view<_Views...>::__iterator; + + template <bool> + friend class zip_view<_Views...>::__sentinel; + + friend class zip_view<_Views...>; + +public: + using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>()); + using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>; + using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>; + + _LIBCPP_HIDE_FROM_ABI + __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator(__iterator<!_Const> __i) + requires _Const && (convertible_to<iterator_t<_Views>, iterator_t<__maybe_const<_Const, _Views>>> && ...) + : __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator*() const { + return ranges::__tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_); + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator++() { + ranges::__tuple_for_each([](auto& __i) { ++__i; }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator++(int) + requires __zip_all_forward<_Const, _Views...> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator--() + requires __zip_all_bidirectional<_Const, _Views...> { + ranges::__tuple_for_each([](auto& __i) { --__i; }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator--(int) + requires __zip_all_bidirectional<_Const, _Views...> { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator+=(difference_type __x) + requires __zip_all_random_access<_Const, _Views...> { + ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i += iter_difference_t<_Iter>(__x); }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator-=(difference_type __x) + requires __zip_all_random_access<_Const, _Views...> { + ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i -= iter_difference_t<_Iter>(__x); }, __current_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator[](difference_type __n) const + requires __zip_all_random_access<_Const, _Views...> { + return ranges::__tuple_transform( + [&]<class _Iter>(_Iter& __i) -> decltype(auto) { return __i[iter_difference_t<_Iter>(__n)]; }, __current_); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires(equality_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) { + if constexpr (__zip_all_bidirectional<_Const, _Views...>) { + return __x.__current_ == __y.__current_; + } else { + return ranges::__tuple_any_equals(__x.__current_, __y.__current_); + } + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> { + return __x.__current_ < __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires __zip_all_random_access<_Const, _Views...> && + (three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) + requires __zip_all_random_access<_Const, _Views...> { + auto __r = __i; + __r += __n; + return __r; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) + requires __zip_all_random_access<_Const, _Views...> { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) + requires __zip_all_random_access<_Const, _Views...> { + auto __r = __i; + __r -= __n; + return __r; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires(sized_sentinel_for<iterator_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_Const, _Views>>> && + ...) { + const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __x.__current_, __y.__current_); + return std::apply( + [](auto... __ds) { + return ranges::min({difference_type(__ds)...}, + [](auto __a, auto __b) { return ranges::__abs(__a) < ranges::__abs(__b); }); + }, + __diffs); + } + + _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>>&>())) && ...) && + (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>>&>())) && + ...)) + requires(indirectly_swappable<iterator_t<__maybe_const<_Const, _Views>>> && ...) { + ranges::__tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); + } +}; + +template <input_range... _Views> + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) +template <bool _Const> +class zip_view<_Views...>::__sentinel { + + __tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __sentinel(__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end) : __end_(__end) {} + + friend class zip_view<_Views...>; + + // hidden friend cannot access private member of iterator because they are friends of friends + template <bool _OtherConst> + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) + __iter_current(zip_view<_Views...>::__iterator<_OtherConst> const& __it) { + return (__it.__current_); + } + +public: + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr __sentinel(__sentinel<!_Const> __i) + requires _Const && (convertible_to<sentinel_t<_Views>, sentinel_t<__maybe_const<_Const, _Views>>> && ...) + : __end_(std::move(__i.__end_)) {} + + template <bool _OtherConst> + requires(sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + return ranges::__tuple_any_equals(__iter_current(__x), __y.__end_); + } + + template <bool _OtherConst> + requires( + sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...> + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __iter_current(__x), __y.__end_); + return std::apply( + [](auto... __ds) { + using _Diff = common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...>; + return ranges::min({_Diff(__ds)...}, + [](auto __a, auto __b) { return ranges::__abs(__a) < ranges::__abs(__b); }); + }, + __diffs); + } + + template <bool _OtherConst> + requires( + sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && + ...) + _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...> + operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) { + return -(__x - __y); + } +}; + +template <class... _Views> +inline constexpr bool enable_borrowed_range<zip_view<_Views...>> = (enable_borrowed_range<_Views> && ...); + +namespace views { +namespace __zip { + +struct __fn { + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()() const noexcept { return empty_view<tuple<>>{}; } + + template <class... _Ranges> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ranges&&... rs) const + noexcept(noexcept(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(rs)...))) + -> decltype(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(rs)...)) { + return zip_view<all_t<_Ranges>...>(std::forward<_Ranges>(rs)...); + } +}; + +} // namespace __zip +inline namespace __cpo { + inline constexpr auto zip = __zip::__fn{}; +} // namespace __cpo +} // namespace views +} // namespace ranges + +#endif // _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ZIP_VIEW_H |