1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___RANGES_TAKE_WHILE_VIEW_H 11 #define _LIBCPP___RANGES_TAKE_WHILE_VIEW_H 12 13 #include <__concepts/constructible.h> 14 #include <__concepts/convertible_to.h> 15 #include <__config> 16 #include <__functional/bind_back.h> 17 #include <__functional/invoke.h> 18 #include <__iterator/concepts.h> 19 #include <__memory/addressof.h> 20 #include <__ranges/access.h> 21 #include <__ranges/all.h> 22 #include <__ranges/concepts.h> 23 #include <__ranges/movable_box.h> 24 #include <__ranges/range_adaptor.h> 25 #include <__ranges/view_interface.h> 26 #include <__type_traits/decay.h> 27 #include <__type_traits/is_nothrow_constructible.h> 28 #include <__type_traits/is_object.h> 29 #include <__type_traits/maybe_const.h> 30 #include <__utility/forward.h> 31 #include <__utility/in_place.h> 32 #include <__utility/move.h> 33 34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 35 # pragma GCC system_header 36 #endif 37 38 _LIBCPP_BEGIN_NAMESPACE_STD 39 40 #if _LIBCPP_STD_VER >= 20 41 42 namespace ranges { 43 44 template <view _View, class _Pred> 45 requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> 46 class take_while_view : public view_interface<take_while_view<_View, _Pred>> { 47 template <bool> 48 class __sentinel; 49 50 _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 51 _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; 52 53 public: 54 _LIBCPP_HIDE_FROM_ABI take_while_view() 55 requires default_initializable<_View> && default_initializable<_Pred> 56 = default; 57 take_while_view(_View __base,_Pred __pred)58 _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred) 59 : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} 60 base()61 _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 62 requires copy_constructible<_View> 63 { 64 return __base_; 65 } 66 base()67 _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 68 pred()69 _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; } 70 begin()71 _LIBCPP_HIDE_FROM_ABI constexpr auto begin() 72 requires(!__simple_view<_View>) 73 { 74 return ranges::begin(__base_); 75 } 76 begin()77 _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const 78 requires range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>> 79 { 80 return ranges::begin(__base_); 81 } 82 end()83 _LIBCPP_HIDE_FROM_ABI constexpr auto end() 84 requires(!__simple_view<_View>) 85 { 86 return __sentinel</*_Const=*/false>(ranges::end(__base_), std::addressof(*__pred_)); 87 } 88 end()89 _LIBCPP_HIDE_FROM_ABI constexpr auto end() const 90 requires range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>> 91 { 92 return __sentinel</*_Const=*/true>(ranges::end(__base_), std::addressof(*__pred_)); 93 } 94 }; 95 96 template <class _Range, class _Pred> 97 take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>; 98 99 template <view _View, class _Pred> 100 requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> 101 template <bool _Const> 102 class take_while_view<_View, _Pred>::__sentinel { 103 using _Base = __maybe_const<_Const, _View>; 104 105 sentinel_t<_Base> __end_ = sentinel_t<_Base>(); 106 const _Pred* __pred_ = nullptr; 107 108 friend class __sentinel<!_Const>; 109 110 public: 111 _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 112 __sentinel(sentinel_t<_Base> __end,const _Pred * __pred)113 _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred) 114 : __end_(std::move(__end)), __pred_(__pred) {} 115 __sentinel(__sentinel<!_Const> __s)116 _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s) 117 requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> 118 : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {} 119 base()120 _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } 121 122 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) { 123 return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); 124 } 125 126 template <bool _OtherConst = !_Const> 127 requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 128 _LIBCPP_HIDE_FROM_ABI friend constexpr bool 129 operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) { 130 return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); 131 } 132 }; 133 134 namespace views { 135 namespace __take_while { 136 137 struct __fn { 138 template <class _Range, class _Pred> 139 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Pred&& __pred) const 140 noexcept(noexcept(/**/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)))) 141 -> decltype(/*--*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred))) { 142 return /*-------------*/ take_while_view(std::forward<_Range>(__range), std::forward<_Pred>(__pred)); 143 } 144 145 template <class _Pred> 146 requires constructible_from<decay_t<_Pred>, _Pred> operator__fn147 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Pred&& __pred) const 148 noexcept(is_nothrow_constructible_v<decay_t<_Pred>, _Pred>) { 149 return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Pred>(__pred))); 150 } 151 }; 152 153 } // namespace __take_while 154 155 inline namespace __cpo { 156 inline constexpr auto take_while = __take_while::__fn{}; 157 } // namespace __cpo 158 } // namespace views 159 } // namespace ranges 160 161 #endif // _LIBCPP_STD_VER >= 20 162 163 _LIBCPP_END_NAMESPACE_STD 164 165 #endif // _LIBCPP___RANGES_TAKE_WHILE_VIEW_H 166