File indexing completed on 2026-05-03 08:14:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___RANGES_CHUNK_BY_VIEW_H
0011 #define _LIBCPP___RANGES_CHUNK_BY_VIEW_H
0012
0013 #include <__algorithm/ranges_adjacent_find.h>
0014 #include <__assert>
0015 #include <__concepts/constructible.h>
0016 #include <__config>
0017 #include <__functional/bind_back.h>
0018 #include <__functional/invoke.h>
0019 #include <__iterator/concepts.h>
0020 #include <__iterator/default_sentinel.h>
0021 #include <__iterator/iterator_traits.h>
0022 #include <__iterator/next.h>
0023 #include <__iterator/prev.h>
0024 #include <__memory/addressof.h>
0025 #include <__ranges/access.h>
0026 #include <__ranges/all.h>
0027 #include <__ranges/concepts.h>
0028 #include <__ranges/movable_box.h>
0029 #include <__ranges/non_propagating_cache.h>
0030 #include <__ranges/range_adaptor.h>
0031 #include <__ranges/reverse_view.h>
0032 #include <__ranges/subrange.h>
0033 #include <__ranges/view_interface.h>
0034 #include <__type_traits/conditional.h>
0035 #include <__type_traits/decay.h>
0036 #include <__type_traits/is_nothrow_constructible.h>
0037 #include <__type_traits/is_object.h>
0038 #include <__utility/forward.h>
0039 #include <__utility/in_place.h>
0040 #include <__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 <__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
0062 using _Cache _LIBCPP_NODEBUG = __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
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
0082 _LIBCPP_ASSERT_PEDANTIC(__current != ranges::begin(__base_), "Trying to call __find_prev() on a begin iterator.");
0083
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
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
0160
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
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 __pipeable(std::__bind_back(*this, std::forward<_Pred>(__pred)));
0219 }
0220 };
0221 }
0222
0223 inline namespace __cpo {
0224 inline constexpr auto chunk_by = __chunk_by::__fn{};
0225 }
0226 }
0227 }
0228
0229 #endif
0230
0231 _LIBCPP_END_NAMESPACE_STD
0232
0233 _LIBCPP_POP_MACROS
0234
0235 #endif