xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/iota_view.h (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric // -*- C++ -*-
2*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
3*349cc55cSDimitry Andric //
4*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*349cc55cSDimitry Andric //
8*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
9*349cc55cSDimitry Andric #ifndef _LIBCPP___RANGES_IOTA_VIEW_H
10*349cc55cSDimitry Andric #define _LIBCPP___RANGES_IOTA_VIEW_H
11*349cc55cSDimitry Andric 
12*349cc55cSDimitry Andric #include <__compare/three_way_comparable.h>
13*349cc55cSDimitry Andric #include <__concepts/arithmetic.h>
14*349cc55cSDimitry Andric #include <__concepts/constructible.h>
15*349cc55cSDimitry Andric #include <__concepts/convertible_to.h>
16*349cc55cSDimitry Andric #include <__concepts/copyable.h>
17*349cc55cSDimitry Andric #include <__concepts/equality_comparable.h>
18*349cc55cSDimitry Andric #include <__concepts/invocable.h>
19*349cc55cSDimitry Andric #include <__concepts/same_as.h>
20*349cc55cSDimitry Andric #include <__concepts/semiregular.h>
21*349cc55cSDimitry Andric #include <__concepts/totally_ordered.h>
22*349cc55cSDimitry Andric #include <__config>
23*349cc55cSDimitry Andric #include <__debug>
24*349cc55cSDimitry Andric #include <__functional/ranges_operations.h>
25*349cc55cSDimitry Andric #include <__iterator/concepts.h>
26*349cc55cSDimitry Andric #include <__iterator/incrementable_traits.h>
27*349cc55cSDimitry Andric #include <__iterator/iterator_traits.h>
28*349cc55cSDimitry Andric #include <__iterator/unreachable_sentinel.h>
29*349cc55cSDimitry Andric #include <__ranges/copyable_box.h>
30*349cc55cSDimitry Andric #include <__ranges/enable_borrowed_range.h>
31*349cc55cSDimitry Andric #include <__ranges/view_interface.h>
32*349cc55cSDimitry Andric #include <__utility/forward.h>
33*349cc55cSDimitry Andric #include <__utility/move.h>
34*349cc55cSDimitry Andric #include <type_traits>
35*349cc55cSDimitry Andric 
36*349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
37*349cc55cSDimitry Andric #pragma GCC system_header
38*349cc55cSDimitry Andric #endif
39*349cc55cSDimitry Andric 
40*349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
41*349cc55cSDimitry Andric 
42*349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_RANGES)
43*349cc55cSDimitry Andric 
44*349cc55cSDimitry Andric namespace ranges {
45*349cc55cSDimitry Andric   template<class _Int>
46*349cc55cSDimitry Andric   struct __get_wider_signed {
47*349cc55cSDimitry Andric     static auto __call() {
48*349cc55cSDimitry Andric            if constexpr (sizeof(_Int) < sizeof(short)) return type_identity<short>{};
49*349cc55cSDimitry Andric       else if constexpr (sizeof(_Int) < sizeof(int))   return type_identity<int>{};
50*349cc55cSDimitry Andric       else if constexpr (sizeof(_Int) < sizeof(long))  return type_identity<long>{};
51*349cc55cSDimitry Andric       else                                             return type_identity<long long>{};
52*349cc55cSDimitry Andric 
53*349cc55cSDimitry Andric       static_assert(sizeof(_Int) <= sizeof(long long),
54*349cc55cSDimitry Andric         "Found integer-like type that is bigger than largest integer like type.");
55*349cc55cSDimitry Andric     }
56*349cc55cSDimitry Andric 
57*349cc55cSDimitry Andric     using type = typename decltype(__call())::type;
58*349cc55cSDimitry Andric   };
59*349cc55cSDimitry Andric 
60*349cc55cSDimitry Andric   template<class _Start>
61*349cc55cSDimitry Andric   using _IotaDiffT = typename _If<
62*349cc55cSDimitry Andric       (!integral<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)),
63*349cc55cSDimitry Andric       type_identity<iter_difference_t<_Start>>,
64*349cc55cSDimitry Andric       __get_wider_signed<_Start>
65*349cc55cSDimitry Andric     >::type;
66*349cc55cSDimitry Andric 
67*349cc55cSDimitry Andric   template<class _Iter>
68*349cc55cSDimitry Andric   concept __decrementable = incrementable<_Iter> && requires(_Iter __i) {
69*349cc55cSDimitry Andric     { --__i } -> same_as<_Iter&>;
70*349cc55cSDimitry Andric     { __i-- } -> same_as<_Iter>;
71*349cc55cSDimitry Andric   };
72*349cc55cSDimitry Andric 
73*349cc55cSDimitry Andric   template<class _Iter>
74*349cc55cSDimitry Andric   concept __advanceable =
75*349cc55cSDimitry Andric     __decrementable<_Iter> && totally_ordered<_Iter> &&
76*349cc55cSDimitry Andric     requires(_Iter __i, const _Iter __j, const _IotaDiffT<_Iter> __n) {
77*349cc55cSDimitry Andric       { __i += __n } -> same_as<_Iter&>;
78*349cc55cSDimitry Andric       { __i -= __n } -> same_as<_Iter&>;
79*349cc55cSDimitry Andric       _Iter(__j + __n);
80*349cc55cSDimitry Andric       _Iter(__n + __j);
81*349cc55cSDimitry Andric       _Iter(__j - __n);
82*349cc55cSDimitry Andric       { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>;
83*349cc55cSDimitry Andric     };
84*349cc55cSDimitry Andric 
85*349cc55cSDimitry Andric   template<class>
86*349cc55cSDimitry Andric   struct __iota_iterator_category {};
87*349cc55cSDimitry Andric 
88*349cc55cSDimitry Andric   template<incrementable _Tp>
89*349cc55cSDimitry Andric   struct __iota_iterator_category<_Tp> {
90*349cc55cSDimitry Andric     using iterator_category = input_iterator_tag;
91*349cc55cSDimitry Andric   };
92*349cc55cSDimitry Andric 
93*349cc55cSDimitry Andric   template<weakly_incrementable _Start, semiregular _Bound = unreachable_sentinel_t>
94*349cc55cSDimitry Andric     requires __weakly_equality_comparable_with<_Start, _Bound> && copyable<_Start>
95*349cc55cSDimitry Andric   class iota_view : public view_interface<iota_view<_Start, _Bound>> {
96*349cc55cSDimitry Andric     struct __iterator : public __iota_iterator_category<_Start> {
97*349cc55cSDimitry Andric       friend class iota_view;
98*349cc55cSDimitry Andric 
99*349cc55cSDimitry Andric       using iterator_concept =
100*349cc55cSDimitry Andric         _If<__advanceable<_Start>,   random_access_iterator_tag,
101*349cc55cSDimitry Andric         _If<__decrementable<_Start>, bidirectional_iterator_tag,
102*349cc55cSDimitry Andric         _If<incrementable<_Start>,   forward_iterator_tag,
103*349cc55cSDimitry Andric         /*Else*/                     input_iterator_tag>>>;
104*349cc55cSDimitry Andric 
105*349cc55cSDimitry Andric       using value_type = _Start;
106*349cc55cSDimitry Andric       using difference_type = _IotaDiffT<_Start>;
107*349cc55cSDimitry Andric 
108*349cc55cSDimitry Andric       _Start __value_ = _Start();
109*349cc55cSDimitry Andric 
110*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
111*349cc55cSDimitry Andric       __iterator() requires default_initializable<_Start> = default;
112*349cc55cSDimitry Andric 
113*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
114*349cc55cSDimitry Andric       constexpr explicit __iterator(_Start __value) : __value_(_VSTD::move(__value)) {}
115*349cc55cSDimitry Andric 
116*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
117*349cc55cSDimitry Andric       constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {
118*349cc55cSDimitry Andric         return __value_;
119*349cc55cSDimitry Andric       }
120*349cc55cSDimitry Andric 
121*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
122*349cc55cSDimitry Andric       constexpr __iterator& operator++() {
123*349cc55cSDimitry Andric         ++__value_;
124*349cc55cSDimitry Andric         return *this;
125*349cc55cSDimitry Andric       }
126*349cc55cSDimitry Andric 
127*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
128*349cc55cSDimitry Andric       constexpr void operator++(int) { ++*this; }
129*349cc55cSDimitry Andric 
130*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
131*349cc55cSDimitry Andric       constexpr __iterator operator++(int) requires incrementable<_Start> {
132*349cc55cSDimitry Andric         auto __tmp = *this;
133*349cc55cSDimitry Andric         ++*this;
134*349cc55cSDimitry Andric         return __tmp;
135*349cc55cSDimitry Andric       }
136*349cc55cSDimitry Andric 
137*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
138*349cc55cSDimitry Andric       constexpr __iterator& operator--() requires __decrementable<_Start> {
139*349cc55cSDimitry Andric         --__value_;
140*349cc55cSDimitry Andric         return *this;
141*349cc55cSDimitry Andric       }
142*349cc55cSDimitry Andric 
143*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
144*349cc55cSDimitry Andric       constexpr __iterator  operator--(int) requires __decrementable<_Start> {
145*349cc55cSDimitry Andric         auto __tmp = *this;
146*349cc55cSDimitry Andric         --*this;
147*349cc55cSDimitry Andric         return __tmp;
148*349cc55cSDimitry Andric       }
149*349cc55cSDimitry Andric 
150*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
151*349cc55cSDimitry Andric       constexpr __iterator& operator+=(difference_type __n)
152*349cc55cSDimitry Andric         requires __advanceable<_Start>
153*349cc55cSDimitry Andric       {
154*349cc55cSDimitry Andric         if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
155*349cc55cSDimitry Andric           if (__n >= difference_type(0)) {
156*349cc55cSDimitry Andric             __value_ += static_cast<_Start>(__n);
157*349cc55cSDimitry Andric           } else {
158*349cc55cSDimitry Andric             __value_ -= static_cast<_Start>(-__n);
159*349cc55cSDimitry Andric           }
160*349cc55cSDimitry Andric         } else {
161*349cc55cSDimitry Andric           __value_ += __n;
162*349cc55cSDimitry Andric         }
163*349cc55cSDimitry Andric         return *this;
164*349cc55cSDimitry Andric       }
165*349cc55cSDimitry Andric 
166*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
167*349cc55cSDimitry Andric       constexpr __iterator& operator-=(difference_type __n)
168*349cc55cSDimitry Andric         requires __advanceable<_Start>
169*349cc55cSDimitry Andric       {
170*349cc55cSDimitry Andric         if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
171*349cc55cSDimitry Andric           if (__n >= difference_type(0)) {
172*349cc55cSDimitry Andric             __value_ -= static_cast<_Start>(__n);
173*349cc55cSDimitry Andric           } else {
174*349cc55cSDimitry Andric             __value_ += static_cast<_Start>(-__n);
175*349cc55cSDimitry Andric           }
176*349cc55cSDimitry Andric         } else {
177*349cc55cSDimitry Andric           __value_ -= __n;
178*349cc55cSDimitry Andric         }
179*349cc55cSDimitry Andric         return *this;
180*349cc55cSDimitry Andric       }
181*349cc55cSDimitry Andric 
182*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
183*349cc55cSDimitry Andric       constexpr _Start operator[](difference_type __n) const
184*349cc55cSDimitry Andric         requires __advanceable<_Start>
185*349cc55cSDimitry Andric       {
186*349cc55cSDimitry Andric         return _Start(__value_ + __n);
187*349cc55cSDimitry Andric       }
188*349cc55cSDimitry Andric 
189*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
190*349cc55cSDimitry Andric       friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
191*349cc55cSDimitry Andric         requires equality_comparable<_Start>
192*349cc55cSDimitry Andric       {
193*349cc55cSDimitry Andric         return __x.__value_ == __y.__value_;
194*349cc55cSDimitry Andric       }
195*349cc55cSDimitry Andric 
196*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
197*349cc55cSDimitry Andric       friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
198*349cc55cSDimitry Andric         requires totally_ordered<_Start>
199*349cc55cSDimitry Andric       {
200*349cc55cSDimitry Andric         return __x.__value_ < __y.__value_;
201*349cc55cSDimitry Andric       }
202*349cc55cSDimitry Andric 
203*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
204*349cc55cSDimitry Andric       friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
205*349cc55cSDimitry Andric         requires totally_ordered<_Start>
206*349cc55cSDimitry Andric       {
207*349cc55cSDimitry Andric         return __y < __x;
208*349cc55cSDimitry Andric       }
209*349cc55cSDimitry Andric 
210*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
211*349cc55cSDimitry Andric       friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
212*349cc55cSDimitry Andric         requires totally_ordered<_Start>
213*349cc55cSDimitry Andric       {
214*349cc55cSDimitry Andric         return !(__y < __x);
215*349cc55cSDimitry Andric       }
216*349cc55cSDimitry Andric 
217*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
218*349cc55cSDimitry Andric       friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
219*349cc55cSDimitry Andric         requires totally_ordered<_Start>
220*349cc55cSDimitry Andric       {
221*349cc55cSDimitry Andric         return !(__x < __y);
222*349cc55cSDimitry Andric       }
223*349cc55cSDimitry Andric 
224*349cc55cSDimitry Andric       friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
225*349cc55cSDimitry Andric         requires totally_ordered<_Start> && three_way_comparable<_Start>
226*349cc55cSDimitry Andric       {
227*349cc55cSDimitry Andric         return __x.__value_ <=> __y.__value_;
228*349cc55cSDimitry Andric       }
229*349cc55cSDimitry Andric 
230*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
231*349cc55cSDimitry Andric       friend constexpr __iterator operator+(__iterator __i, difference_type __n)
232*349cc55cSDimitry Andric         requires __advanceable<_Start>
233*349cc55cSDimitry Andric       {
234*349cc55cSDimitry Andric         __i += __n;
235*349cc55cSDimitry Andric         return __i;
236*349cc55cSDimitry Andric       }
237*349cc55cSDimitry Andric 
238*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
239*349cc55cSDimitry Andric       friend constexpr __iterator operator+(difference_type __n, __iterator __i)
240*349cc55cSDimitry Andric         requires __advanceable<_Start>
241*349cc55cSDimitry Andric       {
242*349cc55cSDimitry Andric         return __i + __n;
243*349cc55cSDimitry Andric       }
244*349cc55cSDimitry Andric 
245*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
246*349cc55cSDimitry Andric       friend constexpr __iterator operator-(__iterator __i, difference_type __n)
247*349cc55cSDimitry Andric         requires __advanceable<_Start>
248*349cc55cSDimitry Andric       {
249*349cc55cSDimitry Andric         __i -= __n;
250*349cc55cSDimitry Andric         return __i;
251*349cc55cSDimitry Andric       }
252*349cc55cSDimitry Andric 
253*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
254*349cc55cSDimitry Andric       friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
255*349cc55cSDimitry Andric         requires __advanceable<_Start>
256*349cc55cSDimitry Andric       {
257*349cc55cSDimitry Andric         if constexpr (__integer_like<_Start>) {
258*349cc55cSDimitry Andric           if constexpr (__signed_integer_like<_Start>) {
259*349cc55cSDimitry Andric             return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
260*349cc55cSDimitry Andric           }
261*349cc55cSDimitry Andric           if (__y.__value_ > __x.__value_) {
262*349cc55cSDimitry Andric             return difference_type(-difference_type(__y.__value_ - __x.__value_));
263*349cc55cSDimitry Andric           }
264*349cc55cSDimitry Andric           return difference_type(__x.__value_ - __y.__value_);
265*349cc55cSDimitry Andric         }
266*349cc55cSDimitry Andric         return __x.__value_ - __y.__value_;
267*349cc55cSDimitry Andric       }
268*349cc55cSDimitry Andric     };
269*349cc55cSDimitry Andric 
270*349cc55cSDimitry Andric     struct __sentinel {
271*349cc55cSDimitry Andric       friend class iota_view;
272*349cc55cSDimitry Andric 
273*349cc55cSDimitry Andric     private:
274*349cc55cSDimitry Andric       _Bound __bound_ = _Bound();
275*349cc55cSDimitry Andric 
276*349cc55cSDimitry Andric     public:
277*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
278*349cc55cSDimitry Andric       __sentinel() = default;
279*349cc55cSDimitry Andric       constexpr explicit __sentinel(_Bound __bound) : __bound_(_VSTD::move(__bound)) {}
280*349cc55cSDimitry Andric 
281*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
282*349cc55cSDimitry Andric       friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
283*349cc55cSDimitry Andric         return __x.__value_ == __y.__bound_;
284*349cc55cSDimitry Andric       }
285*349cc55cSDimitry Andric 
286*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
287*349cc55cSDimitry Andric       friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y)
288*349cc55cSDimitry Andric         requires sized_sentinel_for<_Bound, _Start>
289*349cc55cSDimitry Andric       {
290*349cc55cSDimitry Andric         return __x.__value_ - __y.__bound_;
291*349cc55cSDimitry Andric       }
292*349cc55cSDimitry Andric 
293*349cc55cSDimitry Andric       _LIBCPP_HIDE_FROM_ABI
294*349cc55cSDimitry Andric       friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y)
295*349cc55cSDimitry Andric         requires sized_sentinel_for<_Bound, _Start>
296*349cc55cSDimitry Andric       {
297*349cc55cSDimitry Andric         return -(__y - __x);
298*349cc55cSDimitry Andric       }
299*349cc55cSDimitry Andric     };
300*349cc55cSDimitry Andric 
301*349cc55cSDimitry Andric     _Start __value_ = _Start();
302*349cc55cSDimitry Andric     _Bound __bound_ = _Bound();
303*349cc55cSDimitry Andric 
304*349cc55cSDimitry Andric   public:
305*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
306*349cc55cSDimitry Andric     iota_view() requires default_initializable<_Start> = default;
307*349cc55cSDimitry Andric 
308*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
309*349cc55cSDimitry Andric     constexpr explicit iota_view(_Start __value) : __value_(_VSTD::move(__value)) { }
310*349cc55cSDimitry Andric 
311*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
312*349cc55cSDimitry Andric     constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_Bound> __bound)
313*349cc55cSDimitry Andric       : __value_(_VSTD::move(__value)), __bound_(_VSTD::move(__bound)) {
314*349cc55cSDimitry Andric       // Validate the precondition if possible.
315*349cc55cSDimitry Andric       if constexpr (totally_ordered_with<_Start, _Bound>) {
316*349cc55cSDimitry Andric         _LIBCPP_ASSERT(ranges::less_equal()(__value_, __bound_),
317*349cc55cSDimitry Andric                        "Precondition violated: value is greater than bound.");
318*349cc55cSDimitry Andric       }
319*349cc55cSDimitry Andric     }
320*349cc55cSDimitry Andric 
321*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
322*349cc55cSDimitry Andric     constexpr iota_view(__iterator __first, __iterator __last)
323*349cc55cSDimitry Andric       requires same_as<_Start, _Bound>
324*349cc55cSDimitry Andric       : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__value_)) {}
325*349cc55cSDimitry Andric 
326*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
327*349cc55cSDimitry Andric     constexpr iota_view(__iterator __first, _Bound __last)
328*349cc55cSDimitry Andric       requires same_as<_Bound, unreachable_sentinel_t>
329*349cc55cSDimitry Andric       : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last)) {}
330*349cc55cSDimitry Andric 
331*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
332*349cc55cSDimitry Andric     constexpr iota_view(__iterator __first, __sentinel __last)
333*349cc55cSDimitry Andric       requires (!same_as<_Start, _Bound> && !same_as<_Start, unreachable_sentinel_t>)
334*349cc55cSDimitry Andric       : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__bound_)) {}
335*349cc55cSDimitry Andric 
336*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
337*349cc55cSDimitry Andric     constexpr __iterator begin() const { return __iterator{__value_}; }
338*349cc55cSDimitry Andric 
339*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
340*349cc55cSDimitry Andric     constexpr auto end() const {
341*349cc55cSDimitry Andric       if constexpr (same_as<_Bound, unreachable_sentinel_t>)
342*349cc55cSDimitry Andric         return unreachable_sentinel;
343*349cc55cSDimitry Andric       else
344*349cc55cSDimitry Andric         return __sentinel{__bound_};
345*349cc55cSDimitry Andric     }
346*349cc55cSDimitry Andric 
347*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
348*349cc55cSDimitry Andric     constexpr __iterator end() const requires same_as<_Start, _Bound> {
349*349cc55cSDimitry Andric       return __iterator{__bound_};
350*349cc55cSDimitry Andric     }
351*349cc55cSDimitry Andric 
352*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
353*349cc55cSDimitry Andric     constexpr auto size() const
354*349cc55cSDimitry Andric       requires (same_as<_Start, _Bound> && __advanceable<_Start>) ||
355*349cc55cSDimitry Andric                (integral<_Start> && integral<_Bound>) ||
356*349cc55cSDimitry Andric                sized_sentinel_for<_Bound, _Start>
357*349cc55cSDimitry Andric     {
358*349cc55cSDimitry Andric       if constexpr (__integer_like<_Start> && __integer_like<_Bound>) {
359*349cc55cSDimitry Andric         if (__value_ < 0) {
360*349cc55cSDimitry Andric           if (__bound_ < 0) {
361*349cc55cSDimitry Andric             return _VSTD::__to_unsigned_like(-__value_) - _VSTD::__to_unsigned_like(-__bound_);
362*349cc55cSDimitry Andric           }
363*349cc55cSDimitry Andric           return _VSTD::__to_unsigned_like(__bound_) + _VSTD::__to_unsigned_like(-__value_);
364*349cc55cSDimitry Andric         }
365*349cc55cSDimitry Andric         return _VSTD::__to_unsigned_like(__bound_) - _VSTD::__to_unsigned_like(__value_);
366*349cc55cSDimitry Andric       }
367*349cc55cSDimitry Andric       return _VSTD::__to_unsigned_like(__bound_ - __value_);
368*349cc55cSDimitry Andric     }
369*349cc55cSDimitry Andric   };
370*349cc55cSDimitry Andric 
371*349cc55cSDimitry Andric   template<class _Start, class _Bound>
372*349cc55cSDimitry Andric     requires (!__integer_like<_Start> || !__integer_like<_Bound> ||
373*349cc55cSDimitry Andric               (__signed_integer_like<_Start> == __signed_integer_like<_Bound>))
374*349cc55cSDimitry Andric   iota_view(_Start, _Bound) -> iota_view<_Start, _Bound>;
375*349cc55cSDimitry Andric 
376*349cc55cSDimitry Andric   template<class _Start, class _Bound>
377*349cc55cSDimitry Andric   inline constexpr bool enable_borrowed_range<iota_view<_Start, _Bound>> = true;
378*349cc55cSDimitry Andric 
379*349cc55cSDimitry Andric namespace views {
380*349cc55cSDimitry Andric namespace __iota {
381*349cc55cSDimitry Andric   struct __fn {
382*349cc55cSDimitry Andric     template<class _Start>
383*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
384*349cc55cSDimitry Andric     constexpr auto operator()(_Start&& __start) const
385*349cc55cSDimitry Andric       noexcept(noexcept(ranges::iota_view(_VSTD::forward<_Start>(__start))))
386*349cc55cSDimitry Andric       -> decltype(      ranges::iota_view(_VSTD::forward<_Start>(__start)))
387*349cc55cSDimitry Andric       { return          ranges::iota_view(_VSTD::forward<_Start>(__start)); }
388*349cc55cSDimitry Andric 
389*349cc55cSDimitry Andric     template<class _Start, class _Bound>
390*349cc55cSDimitry Andric     _LIBCPP_HIDE_FROM_ABI
391*349cc55cSDimitry Andric     constexpr auto operator()(_Start&& __start, _Bound&& __bound) const
392*349cc55cSDimitry Andric       noexcept(noexcept(ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound))))
393*349cc55cSDimitry Andric       -> decltype(      ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound)))
394*349cc55cSDimitry Andric       { return          ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound)); }
395*349cc55cSDimitry Andric   };
396*349cc55cSDimitry Andric } // namespace __iota
397*349cc55cSDimitry Andric 
398*349cc55cSDimitry Andric inline namespace __cpo {
399*349cc55cSDimitry Andric   inline constexpr auto iota = __iota::__fn{};
400*349cc55cSDimitry Andric }
401*349cc55cSDimitry Andric } // namespace views
402*349cc55cSDimitry Andric } // namespace ranges
403*349cc55cSDimitry Andric 
404*349cc55cSDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_RANGES)
405*349cc55cSDimitry Andric 
406*349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD
407*349cc55cSDimitry Andric 
408*349cc55cSDimitry Andric #endif // _LIBCPP___RANGES_IOTA_VIEW_H
409