2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___RANGES_TAKE_WHILE_VIEW_H
11 #define _LIBCPP___RANGES_TAKE_WHILE_VIEW_H
13 #include <__concepts/constructible.h>
14 #include <__concepts/convertible_to.h>
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>
34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
35 # pragma GCC system_header
38 _LIBCPP_BEGIN_NAMESPACE_STD
40 #if _LIBCPP_STD_VER >= 20
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
>> {
50 _LIBCPP_NO_UNIQUE_ADDRESS _View __base_
= _View();
51 _LIBCPP_NO_UNIQUE_ADDRESS __movable_box
<_Pred
> __pred_
;
54 _LIBCPP_HIDE_FROM_ABI
take_while_view()
55 requires default_initializable
<_View
> && default_initializable
<_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
)) {}
61 _LIBCPP_HIDE_FROM_ABI
constexpr _View
base() const&
62 requires copy_constructible
<_View
>
67 _LIBCPP_HIDE_FROM_ABI
constexpr _View
base() && { return std::move(__base_
); }
69 _LIBCPP_HIDE_FROM_ABI
constexpr const _Pred
& pred() const { return *__pred_
; }
71 _LIBCPP_HIDE_FROM_ABI
constexpr auto begin()
72 requires(!__simple_view
<_View
>)
74 return ranges::begin(__base_
);
77 _LIBCPP_HIDE_FROM_ABI
constexpr auto begin() const
78 requires range
<const _View
> && indirect_unary_predicate
<const _Pred
, iterator_t
<const _View
>>
80 return ranges::begin(__base_
);
83 _LIBCPP_HIDE_FROM_ABI
constexpr auto end()
84 requires(!__simple_view
<_View
>)
86 return __sentinel
</*_Const=*/false>(ranges::end(__base_
), std::addressof(*__pred_
));
89 _LIBCPP_HIDE_FROM_ABI
constexpr auto end() const
90 requires range
<const _View
> && indirect_unary_predicate
<const _Pred
, iterator_t
<const _View
>>
92 return __sentinel
</*_Const=*/true>(ranges::end(__base_
), std::addressof(*__pred_
));
96 template <class _Range
, class _Pred
>
97 take_while_view(_Range
&&, _Pred
) -> take_while_view
<views::all_t
<_Range
>, _Pred
>;
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
>;
105 sentinel_t
<_Base
> __end_
= sentinel_t
<_Base
>();
106 const _Pred
* __pred_
= nullptr;
108 friend class __sentinel
<!_Const
>;
111 _LIBCPP_HIDE_FROM_ABI
__sentinel() = default;
113 _LIBCPP_HIDE_FROM_ABI
constexpr explicit __sentinel(sentinel_t
<_Base
> __end
, const _Pred
* __pred
)
114 : __end_(std::move(__end
)), __pred_(__pred
) {}
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_
) {}
120 _LIBCPP_HIDE_FROM_ABI
constexpr sentinel_t
<_Base
> base() const { return __end_
; }
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
);
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
);
135 namespace __take_while
{
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
));
145 template <class _Pred
>
146 requires constructible_from
<decay_t
<_Pred
>, _Pred
>
147 [[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
)));
153 } // namespace __take_while
155 inline namespace __cpo
{
156 inline constexpr auto take_while
= __take_while::__fn
{};
159 } // namespace ranges
161 #endif // _LIBCPP_STD_VER >= 20
163 _LIBCPP_END_NAMESPACE_STD
165 #endif // _LIBCPP___RANGES_TAKE_WHILE_VIEW_H