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
14 #include <__concepts/constructible.h>
15 #include <__concepts/same_as.h>
16 #include <__concepts/semiregular.h>
18 #include <__cstddef/ptrdiff_t.h>
19 #include <__iterator/concepts.h>
20 #include <__iterator/iterator_traits.h>
21 #include <__iterator/unreachable_sentinel.h>
22 #include <__memory/addressof.h>
23 #include <__ranges/iota_view.h>
24 #include <__ranges/movable_box.h>
25 #include <__ranges/view_interface.h>
26 #include <__type_traits/decay.h>
27 #include <__type_traits/is_object.h>
28 #include <__type_traits/make_unsigned.h>
29 #include <__type_traits/remove_cv.h>
30 #include <__utility/forward.h>
31 #include <__utility/in_place.h>
32 #include <__utility/move.h>
33 #include <__utility/piecewise_construct.h>
36 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
37 # pragma GCC system_header
41 #include <__undef_macros>
43 _LIBCPP_BEGIN_NAMESPACE_STD
45 #if _LIBCPP_STD_VER >= 23
50 concept __integer_like_with_usable_difference_type
=
51 __signed_integer_like
<_Tp
> || (__integer_like
<_Tp
> && weakly_incrementable
<_Tp
>);
54 struct __repeat_view_iterator_difference
{
55 using type
= _IotaDiffT
<_Tp
>;
58 template <__signed_integer_like _Tp
>
59 struct __repeat_view_iterator_difference
<_Tp
> {
64 using __repeat_view_iterator_difference_t
= typename __repeat_view_iterator_difference
<_Tp
>::type
;
66 namespace views::__drop
{
68 } // namespace views::__drop
70 namespace views::__take
{
72 } // namespace views::__take
74 template <move_constructible _Tp
, semiregular _Bound
= unreachable_sentinel_t
>
75 requires(is_object_v
<_Tp
> && same_as
<_Tp
, remove_cv_t
<_Tp
>> &&
76 (__integer_like_with_usable_difference_type
<_Bound
> || same_as
<_Bound
, unreachable_sentinel_t
>))
77 class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS repeat_view
: public view_interface
<repeat_view
<_Tp
, _Bound
>> {
78 friend struct views::__take::__fn
;
79 friend struct views::__drop::__fn
;
83 _LIBCPP_HIDE_FROM_ABI
repeat_view()
84 requires default_initializable
<_Tp
>
87 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(const _Tp
& __value
, _Bound __bound_sentinel
= _Bound())
88 requires copy_constructible
<_Tp
>
89 : __value_(in_place
, __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 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(_Tp
&& __value
, _Bound __bound_sentinel
= _Bound())
95 : __value_(in_place
, std::move(__value
)), __bound_(__bound_sentinel
) {
96 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
97 _LIBCPP_ASSERT_UNCATEGORIZED(__bound_
>= 0, "The value of bound must be greater than or equal to 0");
100 template <class... _TpArgs
, class... _BoundArgs
>
101 requires(constructible_from
<_Tp
, _TpArgs
...> && constructible_from
<_Bound
, _BoundArgs
...>)
102 _LIBCPP_HIDE_FROM_ABI
constexpr explicit repeat_view(
103 piecewise_construct_t
, tuple
<_TpArgs
...> __value_args
, tuple
<_BoundArgs
...> __bound_args
= tuple
<>{})
104 : __value_(in_place
, std::make_from_tuple
<_Tp
>(std::move(__value_args
))),
105 __bound_(std::make_from_tuple
<_Bound
>(std::move(__bound_args
))) {
106 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
107 _LIBCPP_ASSERT_UNCATEGORIZED(
108 __bound_
>= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative");
111 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
begin() const { return __iterator(std::addressof(*__value_
)); }
113 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
end() const
114 requires(!same_as
<_Bound
, unreachable_sentinel_t
>)
116 return __iterator(std::addressof(*__value_
), __bound_
);
119 _LIBCPP_HIDE_FROM_ABI
constexpr unreachable_sentinel_t
end() const noexcept
{ return unreachable_sentinel
; }
121 _LIBCPP_HIDE_FROM_ABI
constexpr auto size() const
122 requires(!same_as
<_Bound
, unreachable_sentinel_t
>)
124 return std::__to_unsigned_like(__bound_
);
128 _LIBCPP_NO_UNIQUE_ADDRESS __movable_box
<_Tp
> __value_
;
129 _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_
= _Bound();
132 template <class _Tp
, class _Bound
= unreachable_sentinel_t
>
133 repeat_view(_Tp
, _Bound
= _Bound()) -> repeat_view
<_Tp
, _Bound
>;
135 // [range.repeat.iterator]
136 template <move_constructible _Tp
, semiregular _Bound
>
137 requires(is_object_v
<_Tp
> && same_as
<_Tp
, remove_cv_t
<_Tp
>> &&
138 (__integer_like_with_usable_difference_type
<_Bound
> || same_as
<_Bound
, unreachable_sentinel_t
>))
139 class repeat_view
<_Tp
, _Bound
>::__iterator
{
140 friend class repeat_view
;
142 using _IndexT
= conditional_t
<same_as
<_Bound
, unreachable_sentinel_t
>, ptrdiff_t, _Bound
>;
144 _LIBCPP_HIDE_FROM_ABI
constexpr explicit __iterator(const _Tp
* __value
, _IndexT __bound_sentinel
= _IndexT())
145 : __value_(__value
), __current_(__bound_sentinel
) {}
148 using iterator_concept
= random_access_iterator_tag
;
149 using iterator_category
= random_access_iterator_tag
;
150 using value_type
= _Tp
;
151 using difference_type
= __repeat_view_iterator_difference_t
<_IndexT
>;
153 _LIBCPP_HIDE_FROM_ABI
__iterator() = default;
155 _LIBCPP_HIDE_FROM_ABI
constexpr const _Tp
& operator*() const noexcept
{ return *__value_
; }
157 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator++() {
162 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
operator++(int) {
168 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator--() {
169 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
170 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
> 0, "The value of bound must be greater than or equal to 0");
175 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
operator--(int) {
181 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator+=(difference_type __n
) {
182 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
183 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
+ __n
>= 0, "The value of bound must be greater than or equal to 0");
188 _LIBCPP_HIDE_FROM_ABI
constexpr __iterator
& operator-=(difference_type __n
) {
189 if constexpr (!same_as
<_Bound
, unreachable_sentinel_t
>)
190 _LIBCPP_ASSERT_UNCATEGORIZED(__current_
- __n
>= 0, "The value of bound must be greater than or equal to 0");
195 _LIBCPP_HIDE_FROM_ABI
constexpr const _Tp
& operator[](difference_type __n
) const noexcept
{ return *(*this + __n
); }
197 _LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator
& __x
, const __iterator
& __y
) {
198 return __x
.__current_
== __y
.__current_
;
201 _LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __iterator
& __x
, const __iterator
& __y
) {
202 return __x
.__current_
<=> __y
.__current_
;
205 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator+(__iterator __i
, difference_type __n
) {
210 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator+(difference_type __n
, __iterator __i
) {
215 _LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator
operator-(__iterator __i
, difference_type __n
) {
220 _LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type
operator-(const __iterator
& __x
, const __iterator
& __y
) {
221 return static_cast<difference_type
>(__x
.__current_
) - static_cast<difference_type
>(__y
.__current_
);
225 const _Tp
* __value_
= nullptr;
226 _IndexT __current_
= _IndexT();
234 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
static constexpr auto operator()(_Tp
&& __value
)
235 noexcept(noexcept(ranges::repeat_view
<decay_t
<_Tp
>>(std::forward
<_Tp
>(__value
))))
236 -> decltype( ranges::repeat_view
<decay_t
<_Tp
>>(std::forward
<_Tp
>(__value
)))
237 { return ranges::repeat_view
<decay_t
<_Tp
>>(std::forward
<_Tp
>(__value
)); }
239 template <class _Tp
, class _Bound
>
240 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
static constexpr auto operator()(_Tp
&& __value
, _Bound
&& __bound_sentinel
)
241 noexcept(noexcept(ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
))))
242 -> decltype( ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
)))
243 { return ranges::repeat_view(std::forward
<_Tp
>(__value
), std::forward
<_Bound
>(__bound_sentinel
)); }
245 } // namespace __repeat
248 inline namespace __cpo
{
249 inline constexpr auto repeat
= __repeat::__fn
{};
254 inline constexpr bool __is_repeat_specialization
= false;
256 template <class _Tp
, class _Bound
>
257 inline constexpr bool __is_repeat_specialization
<repeat_view
<_Tp
, _Bound
>> = true;
259 } // namespace ranges
261 #endif // _LIBCPP_STD_VER >= 23
263 _LIBCPP_END_NAMESPACE_STD
267 #endif // _LIBCPP___RANGES_REPEAT_VIEW_H