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
39 #include <__undef_macros>
41 _LIBCPP_BEGIN_NAMESPACE_STD
43 #if _LIBCPP_STD_VER >= 20
47 template <view _View
, class _Pred
>
48 requires input_range
<_View
> && is_object_v
<_Pred
> && indirect_unary_predicate
<const _Pred
, iterator_t
<_View
>>
49 class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS take_while_view
: public view_interface
<take_while_view
<_View
, _Pred
>> {
53 _LIBCPP_NO_UNIQUE_ADDRESS _View __base_
= _View();
54 _LIBCPP_NO_UNIQUE_ADDRESS __movable_box
<_Pred
> __pred_
;
57 _LIBCPP_HIDE_FROM_ABI
take_while_view()
58 requires default_initializable
<_View
> && default_initializable
<_Pred
>
61 _LIBCPP_HIDE_FROM_ABI
constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
take_while_view(_View __base
, _Pred __pred
)
62 : __base_(std::move(__base
)), __pred_(std::in_place
, std::move(__pred
)) {}
64 _LIBCPP_HIDE_FROM_ABI
constexpr _View
base() const&
65 requires copy_constructible
<_View
>
70 _LIBCPP_HIDE_FROM_ABI
constexpr _View
base() && { return std::move(__base_
); }
72 _LIBCPP_HIDE_FROM_ABI
constexpr const _Pred
& pred() const { return *__pred_
; }
74 _LIBCPP_HIDE_FROM_ABI
constexpr auto begin()
75 requires(!__simple_view
<_View
>)
77 return ranges::begin(__base_
);
80 _LIBCPP_HIDE_FROM_ABI
constexpr auto begin() const
81 requires range
<const _View
> && indirect_unary_predicate
<const _Pred
, iterator_t
<const _View
>>
83 return ranges::begin(__base_
);
86 _LIBCPP_HIDE_FROM_ABI
constexpr auto end()
87 requires(!__simple_view
<_View
>)
89 return __sentinel
</*_Const=*/false>(ranges::end(__base_
), std::addressof(*__pred_
));
92 _LIBCPP_HIDE_FROM_ABI
constexpr auto end() const
93 requires range
<const _View
> && indirect_unary_predicate
<const _Pred
, iterator_t
<const _View
>>
95 return __sentinel
</*_Const=*/true>(ranges::end(__base_
), std::addressof(*__pred_
));
99 template <class _Range
, class _Pred
>
100 take_while_view(_Range
&&, _Pred
) -> take_while_view
<views::all_t
<_Range
>, _Pred
>;
102 template <view _View
, class _Pred
>
103 requires input_range
<_View
> && is_object_v
<_Pred
> && indirect_unary_predicate
<const _Pred
, iterator_t
<_View
>>
104 template <bool _Const
>
105 class take_while_view
<_View
, _Pred
>::__sentinel
{
106 using _Base
= __maybe_const
<_Const
, _View
>;
108 sentinel_t
<_Base
> __end_
= sentinel_t
<_Base
>();
109 const _Pred
* __pred_
= nullptr;
111 friend class __sentinel
<!_Const
>;
114 _LIBCPP_HIDE_FROM_ABI
__sentinel() = default;
116 _LIBCPP_HIDE_FROM_ABI
constexpr explicit __sentinel(sentinel_t
<_Base
> __end
, const _Pred
* __pred
)
117 : __end_(std::move(__end
)), __pred_(__pred
) {}
119 _LIBCPP_HIDE_FROM_ABI
constexpr __sentinel(__sentinel
<!_Const
> __s
)
120 requires _Const
&& convertible_to
<sentinel_t
<_View
>, sentinel_t
<_Base
>>
121 : __end_(std::move(__s
.__end_
)), __pred_(__s
.__pred_
) {}
123 _LIBCPP_HIDE_FROM_ABI
constexpr sentinel_t
<_Base
> base() const { return __end_
; }
125 _LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const iterator_t
<_Base
>& __x
, const __sentinel
& __y
) {
126 return __x
== __y
.__end_
|| !std::invoke(*__y
.__pred_
, *__x
);
129 template <bool _OtherConst
= !_Const
>
130 requires sentinel_for
<sentinel_t
<_Base
>, iterator_t
<__maybe_const
<_OtherConst
, _View
>>>
131 _LIBCPP_HIDE_FROM_ABI
friend constexpr bool
132 operator==(const iterator_t
<__maybe_const
<_OtherConst
, _View
>>& __x
, const __sentinel
& __y
) {
133 return __x
== __y
.__end_
|| !std::invoke(*__y
.__pred_
, *__x
);
138 namespace __take_while
{
141 template <class _Range
, class _Pred
>
142 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Range
&& __range
, _Pred
&& __pred
) const
143 noexcept(noexcept(/**/ take_while_view(std::forward
<_Range
>(__range
), std::forward
<_Pred
>(__pred
))))
144 -> decltype(/*--*/ take_while_view(std::forward
<_Range
>(__range
), std::forward
<_Pred
>(__pred
))) {
145 return /*-------------*/ take_while_view(std::forward
<_Range
>(__range
), std::forward
<_Pred
>(__pred
));
148 template <class _Pred
>
149 requires constructible_from
<decay_t
<_Pred
>, _Pred
>
150 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Pred
&& __pred
) const
151 noexcept(is_nothrow_constructible_v
<decay_t
<_Pred
>, _Pred
>) {
152 return __pipeable(std::__bind_back(*this, std::forward
<_Pred
>(__pred
)));
156 } // namespace __take_while
158 inline namespace __cpo
{
159 inline constexpr auto take_while
= __take_while::__fn
{};
162 } // namespace ranges
164 #endif // _LIBCPP_STD_VER >= 20
166 _LIBCPP_END_NAMESPACE_STD
170 #endif // _LIBCPP___RANGES_TAKE_WHILE_VIEW_H