Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:40

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03___RANGES_CHUNK_BY_VIEW_H
0011 #define _LIBCPP___CXX03___RANGES_CHUNK_BY_VIEW_H
0012 
0013 #include <__cxx03/__algorithm/ranges_adjacent_find.h>
0014 #include <__cxx03/__assert>
0015 #include <__cxx03/__concepts/constructible.h>
0016 #include <__cxx03/__config>
0017 #include <__cxx03/__functional/bind_back.h>
0018 #include <__cxx03/__functional/invoke.h>
0019 #include <__cxx03/__iterator/concepts.h>
0020 #include <__cxx03/__iterator/default_sentinel.h>
0021 #include <__cxx03/__iterator/iterator_traits.h>
0022 #include <__cxx03/__iterator/next.h>
0023 #include <__cxx03/__iterator/prev.h>
0024 #include <__cxx03/__memory/addressof.h>
0025 #include <__cxx03/__ranges/access.h>
0026 #include <__cxx03/__ranges/all.h>
0027 #include <__cxx03/__ranges/concepts.h>
0028 #include <__cxx03/__ranges/movable_box.h>
0029 #include <__cxx03/__ranges/non_propagating_cache.h>
0030 #include <__cxx03/__ranges/range_adaptor.h>
0031 #include <__cxx03/__ranges/reverse_view.h>
0032 #include <__cxx03/__ranges/subrange.h>
0033 #include <__cxx03/__ranges/view_interface.h>
0034 #include <__cxx03/__type_traits/conditional.h>
0035 #include <__cxx03/__type_traits/decay.h>
0036 #include <__cxx03/__type_traits/is_nothrow_constructible.h>
0037 #include <__cxx03/__type_traits/is_object.h>
0038 #include <__cxx03/__utility/forward.h>
0039 #include <__cxx03/__utility/in_place.h>
0040 #include <__cxx03/__utility/move.h>
0041 
0042 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0043 #  pragma GCC system_header
0044 #endif
0045 
0046 _LIBCPP_PUSH_MACROS
0047 #include <__cxx03/__undef_macros>
0048 
0049 _LIBCPP_BEGIN_NAMESPACE_STD
0050 
0051 #if _LIBCPP_STD_VER >= 23
0052 
0053 namespace ranges {
0054 
0055 template <forward_range _View, indirect_binary_predicate<iterator_t<_View>, iterator_t<_View>> _Pred>
0056   requires view<_View> && is_object_v<_Pred>
0057 class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS chunk_by_view : public view_interface<chunk_by_view<_View, _Pred>> {
0058   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
0059   _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_;
0060 
0061   // We cache the result of begin() to allow providing an amortized O(1).
0062   using _Cache = __non_propagating_cache<iterator_t<_View>>;
0063   _Cache __cached_begin_;
0064 
0065   class __iterator;
0066 
0067   _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> __find_next(iterator_t<_View> __current) {
0068     // Note: this duplicates a check in `optional` but provides a better error message.
0069     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0070         __pred_.__has_value(), "Trying to call __find_next() on a chunk_by_view that does not have a valid predicate.");
0071     auto __reversed_pred = [this]<class _Tp, class _Up>(_Tp&& __x, _Up&& __y) -> bool {
0072       return !std::invoke(*__pred_, std::forward<_Tp>(__x), std::forward<_Up>(__y));
0073     };
0074     return ranges::next(
0075         ranges::adjacent_find(__current, ranges::end(__base_), __reversed_pred), 1, ranges::end(__base_));
0076   }
0077 
0078   _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> __find_prev(iterator_t<_View> __current)
0079     requires bidirectional_range<_View>
0080   {
0081     // Attempting to decrement a begin iterator is a no-op (`__find_prev` would return the same argument given to it).
0082     _LIBCPP_ASSERT_PEDANTIC(__current != ranges::begin(__base_), "Trying to call __find_prev() on a begin iterator.");
0083     // Note: this duplicates a check in `optional` but provides a better error message.
0084     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0085         __pred_.__has_value(), "Trying to call __find_prev() on a chunk_by_view that does not have a valid predicate.");
0086 
0087     auto __first = ranges::begin(__base_);
0088     reverse_view __reversed{subrange{__first, __current}};
0089     auto __reversed_pred = [this]<class _Tp, class _Up>(_Tp&& __x, _Up&& __y) -> bool {
0090       return !std::invoke(*__pred_, std::forward<_Up>(__y), std::forward<_Tp>(__x));
0091     };
0092     return ranges::prev(ranges::adjacent_find(__reversed, __reversed_pred).base(), 1, std::move(__first));
0093   }
0094 
0095 public:
0096   _LIBCPP_HIDE_FROM_ABI chunk_by_view()
0097     requires default_initializable<_View> && default_initializable<_Pred>
0098   = default;
0099 
0100   _LIBCPP_HIDE_FROM_ABI constexpr explicit chunk_by_view(_View __base, _Pred __pred)
0101       : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) {}
0102 
0103   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
0104     requires copy_constructible<_View>
0105   {
0106     return __base_;
0107   }
0108 
0109   _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
0110 
0111   _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; }
0112 
0113   _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() {
0114     // Note: this duplicates a check in `optional` but provides a better error message.
0115     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0116         __pred_.__has_value(), "Trying to call begin() on a chunk_by_view that does not have a valid predicate.");
0117 
0118     auto __first = ranges::begin(__base_);
0119     if (!__cached_begin_.__has_value()) {
0120       __cached_begin_.__emplace(__find_next(__first));
0121     }
0122     return {*this, std::move(__first), *__cached_begin_};
0123   }
0124 
0125   _LIBCPP_HIDE_FROM_ABI constexpr auto end() {
0126     if constexpr (common_range<_View>) {
0127       return __iterator{*this, ranges::end(__base_), ranges::end(__base_)};
0128     } else {
0129       return default_sentinel;
0130     }
0131   }
0132 };
0133 
0134 template <class _Range, class _Pred>
0135 chunk_by_view(_Range&&, _Pred) -> chunk_by_view<views::all_t<_Range>, _Pred>;
0136 
0137 template <forward_range _View, indirect_binary_predicate<iterator_t<_View>, iterator_t<_View>> _Pred>
0138   requires view<_View> && is_object_v<_Pred>
0139 class chunk_by_view<_View, _Pred>::__iterator {
0140   friend chunk_by_view;
0141 
0142   chunk_by_view* __parent_                               = nullptr;
0143   _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>();
0144   _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __next_    = iterator_t<_View>();
0145 
0146   _LIBCPP_HIDE_FROM_ABI constexpr __iterator(
0147       chunk_by_view& __parent, iterator_t<_View> __current, iterator_t<_View> __next)
0148       : __parent_(std::addressof(__parent)), __current_(__current), __next_(__next) {}
0149 
0150 public:
0151   using value_type        = subrange<iterator_t<_View>>;
0152   using difference_type   = range_difference_t<_View>;
0153   using iterator_category = input_iterator_tag;
0154   using iterator_concept  = conditional_t<bidirectional_range<_View>, bidirectional_iterator_tag, forward_iterator_tag>;
0155 
0156   _LIBCPP_HIDE_FROM_ABI __iterator() = default;
0157 
0158   _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const {
0159     // If the iterator is at end, this would return an empty range which can be checked by the calling code and doesn't
0160     // necessarily lead to a bad access.
0161     _LIBCPP_ASSERT_PEDANTIC(__current_ != __next_, "Trying to dereference past-the-end chunk_by_view iterator.");
0162     return {__current_, __next_};
0163   }
0164 
0165   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
0166     // Attempting to increment an end iterator is a no-op (`__find_next` would return the same argument given to it).
0167     _LIBCPP_ASSERT_PEDANTIC(__current_ != __next_, "Trying to increment past end chunk_by_view iterator.");
0168     __current_ = __next_;
0169     __next_    = __parent_->__find_next(__current_);
0170     return *this;
0171   }
0172 
0173   _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) {
0174     auto __tmp = *this;
0175     ++*this;
0176     return __tmp;
0177   }
0178 
0179   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()
0180     requires bidirectional_range<_View>
0181   {
0182     __next_    = __current_;
0183     __current_ = __parent_->__find_prev(__next_);
0184     return *this;
0185   }
0186 
0187   _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int)
0188     requires bidirectional_range<_View>
0189   {
0190     auto __tmp = *this;
0191     --*this;
0192     return __tmp;
0193   }
0194 
0195   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
0196     return __x.__current_ == __y.__current_;
0197   }
0198 
0199   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, default_sentinel_t) {
0200     return __x.__current_ == __x.__next_;
0201   }
0202 };
0203 
0204 namespace views {
0205 namespace __chunk_by {
0206 struct __fn {
0207   template <class _Range, class _Pred>
0208   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const
0209       noexcept(noexcept(/**/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))))
0210           -> decltype(/*--*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) {
0211     return /*-------------*/ chunk_by_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred));
0212   }
0213 
0214   template <class _Pred>
0215     requires constructible_from<decay_t<_Pred>, _Pred>
0216   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const
0217       noexcept(is_nothrow_constructible_v<decay_t<_Pred>, _Pred>) {
0218     return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred)));
0219   }
0220 };
0221 } // namespace __chunk_by
0222 
0223 inline namespace __cpo {
0224 inline constexpr auto chunk_by = __chunk_by::__fn{};
0225 } // namespace __cpo
0226 } // namespace views
0227 } // namespace ranges
0228 
0229 #endif // _LIBCPP_STD_VER >= 23
0230 
0231 _LIBCPP_END_NAMESPACE_STD
0232 
0233 _LIBCPP_POP_MACROS
0234 
0235 #endif // _LIBCPP___CXX03___RANGES_CHUNK_BY_VIEW_H