xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/iota_view.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1349cc55cSDimitry Andric // -*- C++ -*-
2349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
3349cc55cSDimitry Andric //
4349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7349cc55cSDimitry Andric //
8349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
9bdd1243dSDimitry Andric 
10349cc55cSDimitry Andric #ifndef _LIBCPP___RANGES_IOTA_VIEW_H
11349cc55cSDimitry Andric #define _LIBCPP___RANGES_IOTA_VIEW_H
12349cc55cSDimitry Andric 
1381ad6265SDimitry Andric #include <__assert>
14349cc55cSDimitry Andric #include <__compare/three_way_comparable.h>
15349cc55cSDimitry Andric #include <__concepts/arithmetic.h>
16349cc55cSDimitry Andric #include <__concepts/constructible.h>
17349cc55cSDimitry Andric #include <__concepts/convertible_to.h>
18349cc55cSDimitry Andric #include <__concepts/copyable.h>
19349cc55cSDimitry Andric #include <__concepts/equality_comparable.h>
20349cc55cSDimitry Andric #include <__concepts/invocable.h>
21349cc55cSDimitry Andric #include <__concepts/same_as.h>
22349cc55cSDimitry Andric #include <__concepts/semiregular.h>
23349cc55cSDimitry Andric #include <__concepts/totally_ordered.h>
24349cc55cSDimitry Andric #include <__config>
25349cc55cSDimitry Andric #include <__iterator/concepts.h>
26349cc55cSDimitry Andric #include <__iterator/incrementable_traits.h>
27349cc55cSDimitry Andric #include <__iterator/iterator_traits.h>
28349cc55cSDimitry Andric #include <__iterator/unreachable_sentinel.h>
29349cc55cSDimitry Andric #include <__ranges/enable_borrowed_range.h>
3006c3fb27SDimitry Andric #include <__ranges/movable_box.h>
31349cc55cSDimitry Andric #include <__ranges/view_interface.h>
3206c3fb27SDimitry Andric #include <__type_traits/conditional.h>
33*0fca6ea1SDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
3406c3fb27SDimitry Andric #include <__type_traits/make_unsigned.h>
3506c3fb27SDimitry Andric #include <__type_traits/type_identity.h>
36349cc55cSDimitry Andric #include <__utility/forward.h>
37349cc55cSDimitry Andric #include <__utility/move.h>
38349cc55cSDimitry Andric 
39349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
40349cc55cSDimitry Andric #  pragma GCC system_header
41349cc55cSDimitry Andric #endif
42349cc55cSDimitry Andric 
43b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
44b3edf446SDimitry Andric #include <__undef_macros>
45b3edf446SDimitry Andric 
46349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
47349cc55cSDimitry Andric 
4806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
49349cc55cSDimitry Andric 
50349cc55cSDimitry Andric namespace ranges {
51349cc55cSDimitry Andric template <class _Int>
52349cc55cSDimitry Andric struct __get_wider_signed {
5306c3fb27SDimitry Andric   consteval static auto __call() {
54cb14a3feSDimitry Andric     if constexpr (sizeof(_Int) < sizeof(short))
55cb14a3feSDimitry Andric       return type_identity<short>{};
56cb14a3feSDimitry Andric     else if constexpr (sizeof(_Int) < sizeof(int))
57cb14a3feSDimitry Andric       return type_identity<int>{};
58cb14a3feSDimitry Andric     else if constexpr (sizeof(_Int) < sizeof(long))
59cb14a3feSDimitry Andric       return type_identity<long>{};
60cb14a3feSDimitry Andric     else
61cb14a3feSDimitry Andric       return type_identity<long long>{};
62349cc55cSDimitry Andric 
63cb14a3feSDimitry Andric     static_assert(
64cb14a3feSDimitry Andric         sizeof(_Int) <= sizeof(long long), "Found integer-like type that is bigger than largest integer like type.");
65349cc55cSDimitry Andric   }
66349cc55cSDimitry Andric 
67349cc55cSDimitry Andric   using type = typename decltype(__call())::type;
68349cc55cSDimitry Andric };
69349cc55cSDimitry Andric 
70349cc55cSDimitry Andric template <class _Start>
71cb14a3feSDimitry Andric using _IotaDiffT =
72cb14a3feSDimitry Andric     typename _If< (!integral<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)),
73349cc55cSDimitry Andric                   type_identity<iter_difference_t<_Start>>,
74cb14a3feSDimitry Andric                   __get_wider_signed<_Start> >::type;
75349cc55cSDimitry Andric 
76349cc55cSDimitry Andric template <class _Iter>
77349cc55cSDimitry Andric concept __decrementable = incrementable<_Iter> && requires(_Iter __i) {
78349cc55cSDimitry Andric   { --__i } -> same_as<_Iter&>;
79349cc55cSDimitry Andric   { __i-- } -> same_as<_Iter>;
80349cc55cSDimitry Andric };
81349cc55cSDimitry Andric 
82349cc55cSDimitry Andric template <class _Iter>
83349cc55cSDimitry Andric concept __advanceable =
84349cc55cSDimitry Andric     __decrementable<_Iter> && totally_ordered<_Iter> &&
85349cc55cSDimitry Andric     requires(_Iter __i, const _Iter __j, const _IotaDiffT<_Iter> __n) {
86349cc55cSDimitry Andric       { __i += __n } -> same_as<_Iter&>;
87349cc55cSDimitry Andric       { __i -= __n } -> same_as<_Iter&>;
88349cc55cSDimitry Andric       _Iter(__j + __n);
89349cc55cSDimitry Andric       _Iter(__n + __j);
90349cc55cSDimitry Andric       _Iter(__j - __n);
91349cc55cSDimitry Andric       { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>;
92349cc55cSDimitry Andric     };
93349cc55cSDimitry Andric 
94349cc55cSDimitry Andric template <class>
95349cc55cSDimitry Andric struct __iota_iterator_category {};
96349cc55cSDimitry Andric 
97349cc55cSDimitry Andric template <incrementable _Tp>
98349cc55cSDimitry Andric struct __iota_iterator_category<_Tp> {
99349cc55cSDimitry Andric   using iterator_category = input_iterator_tag;
100349cc55cSDimitry Andric };
101349cc55cSDimitry Andric 
10281ad6265SDimitry Andric template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t>
10381ad6265SDimitry Andric   requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
10481ad6265SDimitry Andric class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
1051ac55f4cSDimitry Andric   struct __iterator : public __iota_iterator_category<_Start> {
1061ac55f4cSDimitry Andric     friend class iota_view;
107349cc55cSDimitry Andric 
1081ac55f4cSDimitry Andric     using iterator_concept =
109cb14a3feSDimitry Andric         _If<__advanceable<_Start>,
110cb14a3feSDimitry Andric             random_access_iterator_tag,
111cb14a3feSDimitry Andric             _If<__decrementable<_Start>,
112cb14a3feSDimitry Andric                 bidirectional_iterator_tag,
113cb14a3feSDimitry Andric                 _If<incrementable<_Start>,
114cb14a3feSDimitry Andric                     forward_iterator_tag,
1151ac55f4cSDimitry Andric                     /*Else*/ input_iterator_tag>>>;
1161ac55f4cSDimitry Andric 
1171ac55f4cSDimitry Andric     using value_type      = _Start;
1181ac55f4cSDimitry Andric     using difference_type = _IotaDiffT<_Start>;
1191ac55f4cSDimitry Andric 
1201ac55f4cSDimitry Andric     _Start __value_ = _Start();
1211ac55f4cSDimitry Andric 
122cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI __iterator()
123cb14a3feSDimitry Andric       requires default_initializable<_Start>
124cb14a3feSDimitry Andric     = default;
1251ac55f4cSDimitry Andric 
126cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
1271ac55f4cSDimitry Andric 
128cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {
1291ac55f4cSDimitry Andric       return __value_;
1301ac55f4cSDimitry Andric     }
1311ac55f4cSDimitry Andric 
132cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
1331ac55f4cSDimitry Andric       ++__value_;
1341ac55f4cSDimitry Andric       return *this;
1351ac55f4cSDimitry Andric     }
1361ac55f4cSDimitry Andric 
137cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
1381ac55f4cSDimitry Andric 
139cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int)
140cb14a3feSDimitry Andric       requires incrementable<_Start>
141cb14a3feSDimitry Andric     {
1421ac55f4cSDimitry Andric       auto __tmp = *this;
1431ac55f4cSDimitry Andric       ++*this;
1441ac55f4cSDimitry Andric       return __tmp;
1451ac55f4cSDimitry Andric     }
1461ac55f4cSDimitry Andric 
147cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()
148cb14a3feSDimitry Andric       requires __decrementable<_Start>
149cb14a3feSDimitry Andric     {
1501ac55f4cSDimitry Andric       --__value_;
1511ac55f4cSDimitry Andric       return *this;
1521ac55f4cSDimitry Andric     }
1531ac55f4cSDimitry Andric 
154cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int)
155cb14a3feSDimitry Andric       requires __decrementable<_Start>
156cb14a3feSDimitry Andric     {
1571ac55f4cSDimitry Andric       auto __tmp = *this;
1581ac55f4cSDimitry Andric       --*this;
1591ac55f4cSDimitry Andric       return __tmp;
1601ac55f4cSDimitry Andric     }
1611ac55f4cSDimitry Andric 
162cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n)
1631ac55f4cSDimitry Andric       requires __advanceable<_Start>
1641ac55f4cSDimitry Andric     {
1651ac55f4cSDimitry Andric       if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
1661ac55f4cSDimitry Andric         if (__n >= difference_type(0)) {
1671ac55f4cSDimitry Andric           __value_ += static_cast<_Start>(__n);
1681ac55f4cSDimitry Andric         } else {
1691ac55f4cSDimitry Andric           __value_ -= static_cast<_Start>(-__n);
1701ac55f4cSDimitry Andric         }
1711ac55f4cSDimitry Andric       } else {
1721ac55f4cSDimitry Andric         __value_ += __n;
1731ac55f4cSDimitry Andric       }
1741ac55f4cSDimitry Andric       return *this;
1751ac55f4cSDimitry Andric     }
1761ac55f4cSDimitry Andric 
177cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n)
1781ac55f4cSDimitry Andric       requires __advanceable<_Start>
1791ac55f4cSDimitry Andric     {
1801ac55f4cSDimitry Andric       if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
1811ac55f4cSDimitry Andric         if (__n >= difference_type(0)) {
1821ac55f4cSDimitry Andric           __value_ -= static_cast<_Start>(__n);
1831ac55f4cSDimitry Andric         } else {
1841ac55f4cSDimitry Andric           __value_ += static_cast<_Start>(-__n);
1851ac55f4cSDimitry Andric         }
1861ac55f4cSDimitry Andric       } else {
1871ac55f4cSDimitry Andric         __value_ -= __n;
1881ac55f4cSDimitry Andric       }
1891ac55f4cSDimitry Andric       return *this;
1901ac55f4cSDimitry Andric     }
1911ac55f4cSDimitry Andric 
192cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr _Start operator[](difference_type __n) const
1931ac55f4cSDimitry Andric       requires __advanceable<_Start>
1941ac55f4cSDimitry Andric     {
1951ac55f4cSDimitry Andric       return _Start(__value_ + __n);
1961ac55f4cSDimitry Andric     }
1971ac55f4cSDimitry Andric 
198cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
1991ac55f4cSDimitry Andric       requires equality_comparable<_Start>
2001ac55f4cSDimitry Andric     {
2011ac55f4cSDimitry Andric       return __x.__value_ == __y.__value_;
2021ac55f4cSDimitry Andric     }
2031ac55f4cSDimitry Andric 
204cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
2051ac55f4cSDimitry Andric       requires totally_ordered<_Start>
2061ac55f4cSDimitry Andric     {
2071ac55f4cSDimitry Andric       return __x.__value_ < __y.__value_;
2081ac55f4cSDimitry Andric     }
2091ac55f4cSDimitry Andric 
210cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
2111ac55f4cSDimitry Andric       requires totally_ordered<_Start>
2121ac55f4cSDimitry Andric     {
2131ac55f4cSDimitry Andric       return __y < __x;
2141ac55f4cSDimitry Andric     }
2151ac55f4cSDimitry Andric 
216cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
2171ac55f4cSDimitry Andric       requires totally_ordered<_Start>
2181ac55f4cSDimitry Andric     {
2191ac55f4cSDimitry Andric       return !(__y < __x);
2201ac55f4cSDimitry Andric     }
2211ac55f4cSDimitry Andric 
222cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
2231ac55f4cSDimitry Andric       requires totally_ordered<_Start>
2241ac55f4cSDimitry Andric     {
2251ac55f4cSDimitry Andric       return !(__x < __y);
2261ac55f4cSDimitry Andric     }
2271ac55f4cSDimitry Andric 
228cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
2291ac55f4cSDimitry Andric       requires totally_ordered<_Start> && three_way_comparable<_Start>
2301ac55f4cSDimitry Andric     {
2311ac55f4cSDimitry Andric       return __x.__value_ <=> __y.__value_;
2321ac55f4cSDimitry Andric     }
2331ac55f4cSDimitry Andric 
234cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n)
2351ac55f4cSDimitry Andric       requires __advanceable<_Start>
2361ac55f4cSDimitry Andric     {
2371ac55f4cSDimitry Andric       __i += __n;
2381ac55f4cSDimitry Andric       return __i;
2391ac55f4cSDimitry Andric     }
2401ac55f4cSDimitry Andric 
241cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i)
2421ac55f4cSDimitry Andric       requires __advanceable<_Start>
2431ac55f4cSDimitry Andric     {
2441ac55f4cSDimitry Andric       return __i + __n;
2451ac55f4cSDimitry Andric     }
2461ac55f4cSDimitry Andric 
247cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n)
2481ac55f4cSDimitry Andric       requires __advanceable<_Start>
2491ac55f4cSDimitry Andric     {
2501ac55f4cSDimitry Andric       __i -= __n;
2511ac55f4cSDimitry Andric       return __i;
2521ac55f4cSDimitry Andric     }
2531ac55f4cSDimitry Andric 
254cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
2551ac55f4cSDimitry Andric       requires __advanceable<_Start>
2561ac55f4cSDimitry Andric     {
2571ac55f4cSDimitry Andric       if constexpr (__integer_like<_Start>) {
2581ac55f4cSDimitry Andric         if constexpr (__signed_integer_like<_Start>) {
2591ac55f4cSDimitry Andric           return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
2601ac55f4cSDimitry Andric         }
2611ac55f4cSDimitry Andric         if (__y.__value_ > __x.__value_) {
2621ac55f4cSDimitry Andric           return difference_type(-difference_type(__y.__value_ - __x.__value_));
2631ac55f4cSDimitry Andric         }
2641ac55f4cSDimitry Andric         return difference_type(__x.__value_ - __y.__value_);
2651ac55f4cSDimitry Andric       }
2661ac55f4cSDimitry Andric       return __x.__value_ - __y.__value_;
2671ac55f4cSDimitry Andric     }
2681ac55f4cSDimitry Andric   };
2691ac55f4cSDimitry Andric 
2701ac55f4cSDimitry Andric   struct __sentinel {
2711ac55f4cSDimitry Andric     friend class iota_view;
2721ac55f4cSDimitry Andric 
2731ac55f4cSDimitry Andric   private:
2741ac55f4cSDimitry Andric     _BoundSentinel __bound_sentinel_ = _BoundSentinel();
2751ac55f4cSDimitry Andric 
2761ac55f4cSDimitry Andric   public:
277cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
27806c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel)
27906c3fb27SDimitry Andric         : __bound_sentinel_(std::move(__bound_sentinel)) {}
2801ac55f4cSDimitry Andric 
281cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
2821ac55f4cSDimitry Andric       return __x.__value_ == __y.__bound_sentinel_;
2831ac55f4cSDimitry Andric     }
2841ac55f4cSDimitry Andric 
285cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Start>
286cb14a3feSDimitry Andric     operator-(const __iterator& __x, const __sentinel& __y)
2871ac55f4cSDimitry Andric       requires sized_sentinel_for<_BoundSentinel, _Start>
2881ac55f4cSDimitry Andric     {
2891ac55f4cSDimitry Andric       return __x.__value_ - __y.__bound_sentinel_;
2901ac55f4cSDimitry Andric     }
2911ac55f4cSDimitry Andric 
292cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_Start>
293cb14a3feSDimitry Andric     operator-(const __sentinel& __x, const __iterator& __y)
2941ac55f4cSDimitry Andric       requires sized_sentinel_for<_BoundSentinel, _Start>
2951ac55f4cSDimitry Andric     {
2961ac55f4cSDimitry Andric       return -(__y - __x);
2971ac55f4cSDimitry Andric     }
2981ac55f4cSDimitry Andric   };
299349cc55cSDimitry Andric 
300349cc55cSDimitry Andric   _Start __value_                  = _Start();
30181ad6265SDimitry Andric   _BoundSentinel __bound_sentinel_ = _BoundSentinel();
302349cc55cSDimitry Andric 
303349cc55cSDimitry Andric public:
304cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iota_view()
305cb14a3feSDimitry Andric     requires default_initializable<_Start>
306cb14a3feSDimitry Andric   = default;
307349cc55cSDimitry Andric 
308cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) {}
309349cc55cSDimitry Andric 
310cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
311cb14a3feSDimitry Andric   iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel)
31281ad6265SDimitry Andric       : __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) {
313349cc55cSDimitry Andric     // Validate the precondition if possible.
31481ad6265SDimitry Andric     if constexpr (totally_ordered_with<_Start, _BoundSentinel>) {
315*0fca6ea1SDimitry Andric       _LIBCPP_ASSERT_VALID_INPUT_RANGE(
316*0fca6ea1SDimitry Andric           bool(__value_ <= __bound_sentinel_), "iota_view: bound must be reachable from value");
317349cc55cSDimitry Andric     }
318349cc55cSDimitry Andric   }
319349cc55cSDimitry Andric 
320cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last)
32181ad6265SDimitry Andric     requires same_as<_Start, _BoundSentinel>
32281ad6265SDimitry Andric       : iota_view(std::move(__first.__value_), std::move(__last.__value_)) {}
323349cc55cSDimitry Andric 
324cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last)
32581ad6265SDimitry Andric     requires same_as<_BoundSentinel, unreachable_sentinel_t>
32681ad6265SDimitry Andric       : iota_view(std::move(__first.__value_), std::move(__last)) {}
327349cc55cSDimitry Andric 
328cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last)
32906c3fb27SDimitry Andric     requires(!same_as<_Start, _BoundSentinel> && !same_as<_BoundSentinel, unreachable_sentinel_t>)
33081ad6265SDimitry Andric       : iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {}
331349cc55cSDimitry Andric 
332cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator{__value_}; }
333349cc55cSDimitry Andric 
334cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
33581ad6265SDimitry Andric     if constexpr (same_as<_BoundSentinel, unreachable_sentinel_t>)
336349cc55cSDimitry Andric       return unreachable_sentinel;
337349cc55cSDimitry Andric     else
33881ad6265SDimitry Andric       return __sentinel{__bound_sentinel_};
339349cc55cSDimitry Andric   }
340349cc55cSDimitry Andric 
341cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const
34281ad6265SDimitry Andric     requires same_as<_Start, _BoundSentinel>
34381ad6265SDimitry Andric   {
34481ad6265SDimitry Andric     return __iterator{__bound_sentinel_};
345349cc55cSDimitry Andric   }
346349cc55cSDimitry Andric 
347*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __value_ == __bound_sentinel_; }
348*0fca6ea1SDimitry Andric 
349cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
35081ad6265SDimitry Andric     requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
35181ad6265SDimitry Andric             (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
352349cc55cSDimitry Andric   {
35381ad6265SDimitry Andric     if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {
3545f757f3fSDimitry Andric       return (__value_ < 0)
3555f757f3fSDimitry Andric                ? ((__bound_sentinel_ < 0)
3565f757f3fSDimitry Andric                       ? std::__to_unsigned_like(-__value_) - std::__to_unsigned_like(-__bound_sentinel_)
3575f757f3fSDimitry Andric                       : std::__to_unsigned_like(__bound_sentinel_) + std::__to_unsigned_like(-__value_))
3585f757f3fSDimitry Andric                : std::__to_unsigned_like(__bound_sentinel_) - std::__to_unsigned_like(__value_);
3595f757f3fSDimitry Andric     } else {
36081ad6265SDimitry Andric       return std::__to_unsigned_like(__bound_sentinel_ - __value_);
361349cc55cSDimitry Andric     }
3625f757f3fSDimitry Andric   }
363349cc55cSDimitry Andric };
364349cc55cSDimitry Andric 
36581ad6265SDimitry Andric template <class _Start, class _BoundSentinel>
36681ad6265SDimitry Andric   requires(!__integer_like<_Start> || !__integer_like<_BoundSentinel> ||
36781ad6265SDimitry Andric            (__signed_integer_like<_Start> == __signed_integer_like<_BoundSentinel>))
36881ad6265SDimitry Andric iota_view(_Start, _BoundSentinel) -> iota_view<_Start, _BoundSentinel>;
369349cc55cSDimitry Andric 
37081ad6265SDimitry Andric template <class _Start, class _BoundSentinel>
37181ad6265SDimitry Andric inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true;
372349cc55cSDimitry Andric 
373349cc55cSDimitry Andric namespace views {
374349cc55cSDimitry Andric namespace __iota {
375349cc55cSDimitry Andric struct __fn {
376349cc55cSDimitry Andric   template <class _Start>
377cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start) const
37881ad6265SDimitry Andric       noexcept(noexcept(ranges::iota_view(std::forward<_Start>(__start))))
379cb14a3feSDimitry Andric           -> decltype(ranges::iota_view(std::forward<_Start>(__start))) {
380cb14a3feSDimitry Andric     return ranges::iota_view(std::forward<_Start>(__start));
381cb14a3feSDimitry Andric   }
382349cc55cSDimitry Andric 
38381ad6265SDimitry Andric   template <class _Start, class _BoundSentinel>
384cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Start&& __start, _BoundSentinel&& __bound_sentinel) const noexcept(
385cb14a3feSDimitry Andric       noexcept(ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel))))
386cb14a3feSDimitry Andric       -> decltype(ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel))) {
387cb14a3feSDimitry Andric     return ranges::iota_view(std::forward<_Start>(__start), std::forward<_BoundSentinel>(__bound_sentinel));
388cb14a3feSDimitry Andric   }
389349cc55cSDimitry Andric };
390349cc55cSDimitry Andric } // namespace __iota
391349cc55cSDimitry Andric 
392349cc55cSDimitry Andric inline namespace __cpo {
393349cc55cSDimitry Andric inline constexpr auto iota = __iota::__fn{};
3941fd87a68SDimitry Andric } // namespace __cpo
395349cc55cSDimitry Andric } // namespace views
396349cc55cSDimitry Andric } // namespace ranges
397349cc55cSDimitry Andric 
39806c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
399349cc55cSDimitry Andric 
400349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD
401349cc55cSDimitry Andric 
402b3edf446SDimitry Andric _LIBCPP_POP_MACROS
403b3edf446SDimitry Andric 
404349cc55cSDimitry Andric #endif // _LIBCPP___RANGES_IOTA_VIEW_H
405