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_REPEAT_VIEW_H
11 #define _LIBCPP___RANGES_REPEAT_VIEW_H
13 #include <__concepts/constructible.h>
14 #include <__concepts/same_as.h>
15 #include <__concepts/semiregular.h>
17 #include <__iterator/concepts.h>
18 #include <__iterator/iterator_traits.h>
19 #include <__iterator/unreachable_sentinel.h>
20 #include <__memory/addressof.h>
21 #include <__ranges/iota_view.h>
22 #include <__ranges/movable_box.h>
23 #include <__ranges/view_interface.h>
24 #include <__type_traits/is_object.h>
25 #include <__type_traits/make_unsigned.h>
26 #include <__type_traits/remove_cv.h>
27 #include <__utility/forward.h>
28 #include <__utility/in_place.h>
29 #include <__utility/move.h>
30 #include <__utility/piecewise_construct.h>
33 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
34 # pragma GCC system_header
37 _LIBCPP_BEGIN_NAMESPACE_STD
39 #if _LIBCPP_STD_VER >= 23
44 concept __integer_like_with_usable_difference_type
=
45 __signed_integer_like
<_Tp
> || (__integer_like
<_Tp
> && weakly_incrementable
<_Tp
>);
48 struct __repeat_view_iterator_difference
{
49 using type
= _IotaDiffT
<_Tp
>;
52 template <__signed_integer_like _Tp
>
53 struct __repeat_view_iterator_difference
<_Tp
> {
58 using __repeat_view_iterator_difference_t
= typename __repeat_view_iterator_difference
<_Tp
>::type
;
60 namespace views::__drop
{
62 } // namespace views::__drop
64 namespace views::__take
{
66 } // namespace views::__take
68 template <move_constructible _Tp
, semiregular _Bound
= unreachable_sentinel_t
>
69 requires(is_object_v
<_Tp
> && same_as
<_Tp
, remove_cv_t
<_Tp
>> &&
70 (__integer_like_with_usable_difference_type
<_Bound
> || same_as
<_Bound
, unreachable_sentinel_t
>))
71 class repeat_view
: public view_interface
<repeat_view
<_Tp
, _Bound
>> {
72 friend struct views::__take::__fn
;
73 friend struct views::__drop::__fn
;
77 _LIBCPP_HIDE_FROM_ABI
repeat_view()
78 requires default_initializable
<_Tp
>
81 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(const _Tp
& __value
, _Bound __bound_sentinel
= _Bound())
82 requires copy_constructible
<_Tp
>
83 : __value_(in_place
, __value
), __bound_(__bound_sentinel
) {
84 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
85 _LIBCPP_ASSERT_UNCATEGORIZED(__bound_
>= 0, "The value of bound must be greater than or equal to 0");
88 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(_Tp
&& __value
, _Bound __bound_sentinel
= _Bound())
89 : __value_(in_place
, std::move(__value
)), __bound_(__bound_sentinel
) {
90 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
91 _LIBCPP_ASSERT_UNCATEGORIZED(__bound_
>= 0, "The value of bound must be greater than or equal to 0");
94 template <class... _TpArgs
, class... _BoundArgs
>
95 requires(constructible_from
<_Tp
, _TpArgs
...> && constructible_from
<_Bound
, _BoundArgs
...>)
96 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(
97 piecewise_construct_t
, tuple
<_TpArgs
...> __value_args
, tuple
<_BoundArgs
...> __bound_args
= tuple
<>{})
98 : __value_(in_place
, std::make_from_tuple
<_Tp
>(std::move(__value_args
))),
99 __bound_(std::make_from_tuple
<_Bound
>(std::move(__bound_args
))) {
100 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
101 _LIBCPP_ASSERT_UNCATEGORIZED(
102 __bound_
>= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative");
105 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
begin() const { return __iterator(std::addressof(*__value_
)); }
107 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
end() const
108 requires(!same_as
<_Bound
, unreachable_sentinel_t
>)
110 return __iterator(std::addressof(*__value_
), __bound_
);
113 _LIBCPP_HIDE_FROM_ABI
constexpr unreachable_sentinel_t
end() const noexcept
{ return unreachable_sentinel
; }
115 _LIBCPP_HIDE_FROM_ABI
constexpr auto size() const
116 requires(!same_as
<_Bound
, unreachable_sentinel_t
>)
118 return std::__to_unsigned_like(__bound_
);
122 __movable_box
<_Tp
> __value_
;
123 _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_
= _Bound();
126 template <class _Tp
, class _Bound
>
127 repeat_view(_Tp
, _Bound
) -> repeat_view
<_Tp
, _Bound
>;
129 // [range.repeat.iterator]
130 template <move_constructible _Tp
, semiregular _Bound
>
131 requires(is_object_v
<_Tp
> && same_as
<_Tp
, remove_cv_t
<_Tp
>> &&
132 (__integer_like_with_usable_difference_type
<_Bound
> || same_as
<_Bound
, unreachable_sentinel_t
>))
133 class repeat_view
<_Tp
, _Bound
>::__iterator
{
134 friend class repeat_view
;
136 using _IndexT
= conditional_t
<same_as
<_Bound
, unreachable_sentinel_t
>, ptrdiff_t, _Bound
>;
138 _LIBCPP_HIDE_FROM_ABI
constexpr explicit __iterator(const _Tp
* __value
, _IndexT __bound_sentinel
= _IndexT())
139 : __value_(__value
), __current_(__bound_sentinel
) {}
142 using iterator_concept
= random_access_iterator_tag
;
143 using iterator_category
= random_access_iterator_tag
;
144 using value_type
= _Tp
;
145 using difference_type
= __repeat_view_iterator_difference_t
<_IndexT
>;
147 _LIBCPP_HIDE_FROM_ABI
__iterator() = default;
149 _LIBCPP_HIDE_FROM_ABI
constexpr const _Tp
& operator*() const noexcept
{ return *__value_
; }
151 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator++() {
156 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
operator++(int) {
162 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator--() {
163 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
164 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
> 0, "The value of bound must be greater than or equal to 0");
169 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
operator--(int) {
175 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator+=(difference_type __n
) {
176 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
177 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
+ __n
>= 0, "The value of bound must be greater than or equal to 0");
182 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator-=(difference_type __n
) {
183 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
184 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
- __n
>= 0, "The value of bound must be greater than or equal to 0");
189 _LIBCPP_HIDE_FROM_ABI
constexpr const _Tp
& operator[](difference_type __n
) const noexcept
{ return *(*this + __n
); }
191 _LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator
& __x
, const __iterator
& __y
) {
192 return __x
.__current_
== __y
.__current_
;
195 _LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __iterator
& __x
, const __iterator
& __y
) {
196 return __x
.__current_
<=> __y
.__current_
;
199 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator+(__iterator __i
, difference_type __n
) {
204 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator+(difference_type __n
, __iterator __i
) {
209 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator-(__iterator __i
, difference_type __n
) {
214 _LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type
operator-(const __iterator
& __x
, const __iterator
& __y
) {
215 return static_cast<difference_type
>(__x
.__current_
) - static_cast<difference_type
>(__y
.__current_
);
219 const _Tp
* __value_
= nullptr;
220 _IndexT __current_
= _IndexT();
228 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __value
) const
229 noexcept(noexcept(ranges::repeat_view(std::forward
<_Tp
>(__value
))))
230 -> decltype( ranges::repeat_view(std::forward
<_Tp
>(__value
)))
231 { return ranges::repeat_view(std::forward
<_Tp
>(__value
)); }
234 template <class _Tp
, class _Bound
>
235 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __value
, _Bound
&& __bound_sentinel
) const
236 noexcept(noexcept(ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
))))
237 -> decltype( ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
)))
238 { return ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
)); }
240 } // namespace __repeat
243 inline namespace __cpo
{
244 inline constexpr auto repeat
= __repeat::__fn
{};
249 inline constexpr bool __is_repeat_specialization
= false;
251 template <class _Tp
, class _Bound
>
252 inline constexpr bool __is_repeat_specialization
<repeat_view
<_Tp
, _Bound
>> = true;
254 } // namespace ranges
256 #endif // _LIBCPP_STD_VER >= 23
258 _LIBCPP_END_NAMESPACE_STD
260 #endif // _LIBCPP___RANGES_REPEAT_VIEW_H