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_IOTA_VIEW_H
11 #define _LIBCPP___RANGES_IOTA_VIEW_H
14 #include <__compare/three_way_comparable.h>
15 #include <__concepts/arithmetic.h>
16 #include <__concepts/constructible.h>
17 #include <__concepts/convertible_to.h>
18 #include <__concepts/copyable.h>
19 #include <__concepts/equality_comparable.h>
20 #include <__concepts/invocable.h>
21 #include <__concepts/same_as.h>
22 #include <__concepts/semiregular.h>
23 #include <__concepts/totally_ordered.h>
25 #include <__functional/ranges_operations.h>
26 #include <__iterator/concepts.h>
27 #include <__iterator/incrementable_traits.h>
28 #include <__iterator/iterator_traits.h>
29 #include <__iterator/unreachable_sentinel.h>
30 #include <__ranges/enable_borrowed_range.h>
31 #include <__ranges/movable_box.h>
32 #include <__ranges/view_interface.h>
33 #include <__type_traits/conditional.h>
34 #include <__type_traits/is_nothrow_copy_constructible.h>
35 #include <__type_traits/make_unsigned.h>
36 #include <__type_traits/type_identity.h>
37 #include <__utility/forward.h>
38 #include <__utility/move.h>
40 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
41 # pragma GCC system_header
44 _LIBCPP_BEGIN_NAMESPACE_STD
46 #if _LIBCPP_STD_VER >= 20
50 struct __get_wider_signed
{
51 consteval
static auto __call() {
52 if constexpr (sizeof(_Int
) < sizeof(short)) return type_identity
<short>{};
53 else if constexpr (sizeof(_Int
) < sizeof(int)) return type_identity
<int>{};
54 else if constexpr (sizeof(_Int
) < sizeof(long)) return type_identity
<long>{};
55 else return type_identity
<long long>{};
57 static_assert(sizeof(_Int
) <= sizeof(long long),
58 "Found integer-like type that is bigger than largest integer like type.");
61 using type
= typename
decltype(__call())::type
;
64 template<class _Start
>
65 using _IotaDiffT
= typename _If
<
66 (!integral
<_Start
> || sizeof(iter_difference_t
<_Start
>) > sizeof(_Start
)),
67 type_identity
<iter_difference_t
<_Start
>>,
68 __get_wider_signed
<_Start
>
72 concept __decrementable
= incrementable
<_Iter
> && requires(_Iter __i
) {
73 { --__i
} -> same_as
<_Iter
&>;
74 { __i
-- } -> same_as
<_Iter
>;
78 concept __advanceable
=
79 __decrementable
<_Iter
> && totally_ordered
<_Iter
> &&
80 requires(_Iter __i
, const _Iter __j
, const _IotaDiffT
<_Iter
> __n
) {
81 { __i
+= __n
} -> same_as
<_Iter
&>;
82 { __i
-= __n
} -> same_as
<_Iter
&>;
86 { __j
- __j
} -> convertible_to
<_IotaDiffT
<_Iter
>>;
90 struct __iota_iterator_category
{};
92 template<incrementable _Tp
>
93 struct __iota_iterator_category
<_Tp
> {
94 using iterator_category
= input_iterator_tag
;
97 template <weakly_incrementable _Start
, semiregular _BoundSentinel
= unreachable_sentinel_t
>
98 requires __weakly_equality_comparable_with
<_Start
, _BoundSentinel
> && copyable
<_Start
>
99 class iota_view
: public view_interface
<iota_view
<_Start
, _BoundSentinel
>> {
100 struct __iterator
: public __iota_iterator_category
<_Start
> {
101 friend class iota_view
;
103 using iterator_concept
=
104 _If
<__advanceable
<_Start
>, random_access_iterator_tag
,
105 _If
<__decrementable
<_Start
>, bidirectional_iterator_tag
,
106 _If
<incrementable
<_Start
>, forward_iterator_tag
,
107 /*Else*/ input_iterator_tag
>>>;
109 using value_type
= _Start
;
110 using difference_type
= _IotaDiffT
<_Start
>;
112 _Start __value_
= _Start();
114 _LIBCPP_HIDE_FROM_ABI
115 __iterator() requires default_initializable
<_Start
> = default;
117 _LIBCPP_HIDE_FROM_ABI
118 constexpr explicit __iterator(_Start __value
) : __value_(std::move(__value
)) {}
120 _LIBCPP_HIDE_FROM_ABI
121 constexpr _Start
operator*() const noexcept(is_nothrow_copy_constructible_v
<_Start
>) {
125 _LIBCPP_HIDE_FROM_ABI
126 constexpr __iterator
& operator++() {
131 _LIBCPP_HIDE_FROM_ABI
132 constexpr void operator++(int) { ++*this; }
134 _LIBCPP_HIDE_FROM_ABI
135 constexpr __iterator
operator++(int) requires incrementable
<_Start
> {
141 _LIBCPP_HIDE_FROM_ABI
142 constexpr __iterator
& operator--() requires __decrementable
<_Start
> {
147 _LIBCPP_HIDE_FROM_ABI
148 constexpr __iterator
operator--(int) requires __decrementable
<_Start
> {
154 _LIBCPP_HIDE_FROM_ABI
155 constexpr __iterator
& operator+=(difference_type __n
)
156 requires __advanceable
<_Start
>
158 if constexpr (__integer_like
<_Start
> && !__signed_integer_like
<_Start
>) {
159 if (__n
>= difference_type(0)) {
160 __value_
+= static_cast<_Start
>(__n
);
162 __value_
-= static_cast<_Start
>(-__n
);
170 _LIBCPP_HIDE_FROM_ABI
171 constexpr __iterator
& operator-=(difference_type __n
)
172 requires __advanceable
<_Start
>
174 if constexpr (__integer_like
<_Start
> && !__signed_integer_like
<_Start
>) {
175 if (__n
>= difference_type(0)) {
176 __value_
-= static_cast<_Start
>(__n
);
178 __value_
+= static_cast<_Start
>(-__n
);
186 _LIBCPP_HIDE_FROM_ABI
187 constexpr _Start
operator[](difference_type __n
) const
188 requires __advanceable
<_Start
>
190 return _Start(__value_
+ __n
);
193 _LIBCPP_HIDE_FROM_ABI
194 friend constexpr bool operator==(const __iterator
& __x
, const __iterator
& __y
)
195 requires equality_comparable
<_Start
>
197 return __x
.__value_
== __y
.__value_
;
200 _LIBCPP_HIDE_FROM_ABI
201 friend constexpr bool operator<(const __iterator
& __x
, const __iterator
& __y
)
202 requires totally_ordered
<_Start
>
204 return __x
.__value_
< __y
.__value_
;
207 _LIBCPP_HIDE_FROM_ABI
208 friend constexpr bool operator>(const __iterator
& __x
, const __iterator
& __y
)
209 requires totally_ordered
<_Start
>
214 _LIBCPP_HIDE_FROM_ABI
215 friend constexpr bool operator<=(const __iterator
& __x
, const __iterator
& __y
)
216 requires totally_ordered
<_Start
>
221 _LIBCPP_HIDE_FROM_ABI
222 friend constexpr bool operator>=(const __iterator
& __x
, const __iterator
& __y
)
223 requires totally_ordered
<_Start
>
228 _LIBCPP_HIDE_FROM_ABI
229 friend constexpr auto operator<=>(const __iterator
& __x
, const __iterator
& __y
)
230 requires totally_ordered
<_Start
> && three_way_comparable
<_Start
>
232 return __x
.__value_
<=> __y
.__value_
;
235 _LIBCPP_HIDE_FROM_ABI
236 friend constexpr __iterator
operator+(__iterator __i
, difference_type __n
)
237 requires __advanceable
<_Start
>
243 _LIBCPP_HIDE_FROM_ABI
244 friend constexpr __iterator
operator+(difference_type __n
, __iterator __i
)
245 requires __advanceable
<_Start
>
250 _LIBCPP_HIDE_FROM_ABI
251 friend constexpr __iterator
operator-(__iterator __i
, difference_type __n
)
252 requires __advanceable
<_Start
>
258 _LIBCPP_HIDE_FROM_ABI
259 friend constexpr difference_type
operator-(const __iterator
& __x
, const __iterator
& __y
)
260 requires __advanceable
<_Start
>
262 if constexpr (__integer_like
<_Start
>) {
263 if constexpr (__signed_integer_like
<_Start
>) {
264 return difference_type(difference_type(__x
.__value_
) - difference_type(__y
.__value_
));
266 if (__y
.__value_
> __x
.__value_
) {
267 return difference_type(-difference_type(__y
.__value_
- __x
.__value_
));
269 return difference_type(__x
.__value_
- __y
.__value_
);
271 return __x
.__value_
- __y
.__value_
;
276 friend class iota_view
;
279 _BoundSentinel __bound_sentinel_
= _BoundSentinel();
282 _LIBCPP_HIDE_FROM_ABI
283 __sentinel() = default;
284 _LIBCPP_HIDE_FROM_ABI
constexpr explicit __sentinel(_BoundSentinel __bound_sentinel
)
285 : __bound_sentinel_(std::move(__bound_sentinel
)) {}
287 _LIBCPP_HIDE_FROM_ABI
288 friend constexpr bool operator==(const __iterator
& __x
, const __sentinel
& __y
) {
289 return __x
.__value_
== __y
.__bound_sentinel_
;
292 _LIBCPP_HIDE_FROM_ABI
293 friend constexpr iter_difference_t
<_Start
> operator-(const __iterator
& __x
, const __sentinel
& __y
)
294 requires sized_sentinel_for
<_BoundSentinel
, _Start
>
296 return __x
.__value_
- __y
.__bound_sentinel_
;
299 _LIBCPP_HIDE_FROM_ABI
300 friend constexpr iter_difference_t
<_Start
> operator-(const __sentinel
& __x
, const __iterator
& __y
)
301 requires sized_sentinel_for
<_BoundSentinel
, _Start
>
307 _Start __value_
= _Start();
308 _BoundSentinel __bound_sentinel_
= _BoundSentinel();
311 _LIBCPP_HIDE_FROM_ABI
312 iota_view() requires default_initializable
<_Start
> = default;
314 _LIBCPP_HIDE_FROM_ABI
315 constexpr explicit iota_view(_Start __value
) : __value_(std::move(__value
)) { }
317 _LIBCPP_HIDE_FROM_ABI
318 constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
iota_view(type_identity_t
<_Start
> __value
, type_identity_t
<_BoundSentinel
> __bound_sentinel
)
319 : __value_(std::move(__value
)), __bound_sentinel_(std::move(__bound_sentinel
)) {
320 // Validate the precondition if possible.
321 if constexpr (totally_ordered_with
<_Start
, _BoundSentinel
>) {
322 _LIBCPP_ASSERT_UNCATEGORIZED(ranges::less_equal()(__value_
, __bound_sentinel_
),
323 "Precondition violated: value is greater than bound.");
327 _LIBCPP_HIDE_FROM_ABI
328 constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
iota_view(__iterator __first
, __iterator __last
)
329 requires same_as
<_Start
, _BoundSentinel
>
330 : iota_view(std::move(__first
.__value_
), std::move(__last
.__value_
)) {}
332 _LIBCPP_HIDE_FROM_ABI
333 constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
iota_view(__iterator __first
, _BoundSentinel __last
)
334 requires same_as
<_BoundSentinel
, unreachable_sentinel_t
>
335 : iota_view(std::move(__first
.__value_
), std::move(__last
)) {}
337 _LIBCPP_HIDE_FROM_ABI
338 constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
iota_view(__iterator __first
, __sentinel __last
)
339 requires(!same_as
<_Start
, _BoundSentinel
> && !same_as
<_BoundSentinel
, unreachable_sentinel_t
>)
340 : iota_view(std::move(__first
.__value_
), std::move(__last
.__bound_sentinel_
)) {}
342 _LIBCPP_HIDE_FROM_ABI
343 constexpr __iterator
begin() const { return __iterator
{__value_
}; }
345 _LIBCPP_HIDE_FROM_ABI
346 constexpr auto end() const {
347 if constexpr (same_as
<_BoundSentinel
, unreachable_sentinel_t
>)
348 return unreachable_sentinel
;
350 return __sentinel
{__bound_sentinel_
};
353 _LIBCPP_HIDE_FROM_ABI
354 constexpr __iterator
end() const
355 requires same_as
<_Start
, _BoundSentinel
>
357 return __iterator
{__bound_sentinel_
};
360 _LIBCPP_HIDE_FROM_ABI
361 constexpr auto size() const
362 requires(same_as
<_Start
, _BoundSentinel
> && __advanceable
<_Start
>) ||
363 (integral
<_Start
> && integral
<_BoundSentinel
>) || sized_sentinel_for
<_BoundSentinel
, _Start
>
365 if constexpr (__integer_like
<_Start
> && __integer_like
<_BoundSentinel
>) {
366 return (__value_
< 0)
367 ? ((__bound_sentinel_
< 0)
368 ? std::__to_unsigned_like(-__value_
) - std::__to_unsigned_like(-__bound_sentinel_
)
369 : std::__to_unsigned_like(__bound_sentinel_
) + std::__to_unsigned_like(-__value_
))
370 : std::__to_unsigned_like(__bound_sentinel_
) - std::__to_unsigned_like(__value_
);
372 return std::__to_unsigned_like(__bound_sentinel_
- __value_
);
377 template <class _Start
, class _BoundSentinel
>
378 requires(!__integer_like
<_Start
> || !__integer_like
<_BoundSentinel
> ||
379 (__signed_integer_like
<_Start
> == __signed_integer_like
<_BoundSentinel
>))
380 iota_view(_Start
, _BoundSentinel
) -> iota_view
<_Start
, _BoundSentinel
>;
382 template <class _Start
, class _BoundSentinel
>
383 inline constexpr bool enable_borrowed_range
<iota_view
<_Start
, _BoundSentinel
>> = true;
388 template<class _Start
>
389 _LIBCPP_HIDE_FROM_ABI
390 constexpr auto operator()(_Start
&& __start
) const
391 noexcept(noexcept(ranges::iota_view(std::forward
<_Start
>(__start
))))
392 -> decltype( ranges::iota_view(std::forward
<_Start
>(__start
)))
393 { return ranges::iota_view(std::forward
<_Start
>(__start
)); }
395 template <class _Start
, class _BoundSentinel
>
396 _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Start
&& __start
, _BoundSentinel
&& __bound_sentinel
) const
397 noexcept(noexcept(ranges::iota_view(std::forward
<_Start
>(__start
), std::forward
<_BoundSentinel
>(__bound_sentinel
))))
398 -> decltype( ranges::iota_view(std::forward
<_Start
>(__start
), std::forward
<_BoundSentinel
>(__bound_sentinel
)))
399 { return ranges::iota_view(std::forward
<_Start
>(__start
), std::forward
<_BoundSentinel
>(__bound_sentinel
)); }
401 } // namespace __iota
403 inline namespace __cpo
{
404 inline constexpr auto iota
= __iota::__fn
{};
407 } // namespace ranges
409 #endif // _LIBCPP_STD_VER >= 20
411 _LIBCPP_END_NAMESPACE_STD
413 #endif // _LIBCPP___RANGES_IOTA_VIEW_H