xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/subrange.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric // -*- C++ -*-
2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9bdd1243dSDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_SUBRANGE_H
11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_SUBRANGE_H
12fe6060f1SDimitry Andric 
1381ad6265SDimitry Andric #include <__assert>
14349cc55cSDimitry Andric #include <__concepts/constructible.h>
15349cc55cSDimitry Andric #include <__concepts/convertible_to.h>
16349cc55cSDimitry Andric #include <__concepts/copyable.h>
17349cc55cSDimitry Andric #include <__concepts/derived_from.h>
18349cc55cSDimitry Andric #include <__concepts/different_from.h>
19fe6060f1SDimitry Andric #include <__config>
20bdd1243dSDimitry Andric #include <__fwd/subrange.h>
21349cc55cSDimitry Andric #include <__iterator/advance.h>
22fe6060f1SDimitry Andric #include <__iterator/concepts.h>
23fe6060f1SDimitry Andric #include <__iterator/incrementable_traits.h>
24fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
25fe6060f1SDimitry Andric #include <__ranges/access.h>
26fe6060f1SDimitry Andric #include <__ranges/concepts.h>
27fe6060f1SDimitry Andric #include <__ranges/dangling.h>
28fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h>
29fe6060f1SDimitry Andric #include <__ranges/size.h>
30fe6060f1SDimitry Andric #include <__ranges/view_interface.h>
3106c3fb27SDimitry Andric #include <__tuple/tuple_element.h>
32*0fca6ea1SDimitry Andric #include <__tuple/tuple_like_no_subrange.h>
3306c3fb27SDimitry Andric #include <__tuple/tuple_size.h>
34bdd1243dSDimitry Andric #include <__type_traits/conditional.h>
35bdd1243dSDimitry Andric #include <__type_traits/decay.h>
36bdd1243dSDimitry Andric #include <__type_traits/is_pointer.h>
37bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
38bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h>
39bdd1243dSDimitry Andric #include <__type_traits/remove_const.h>
40bdd1243dSDimitry Andric #include <__type_traits/remove_pointer.h>
41349cc55cSDimitry Andric #include <__utility/move.h>
42bdd1243dSDimitry Andric #include <cstddef>
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
45fe6060f1SDimitry Andric #  pragma GCC system_header
46fe6060f1SDimitry Andric #endif
47fe6060f1SDimitry Andric 
4806c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
4906c3fb27SDimitry Andric #include <__undef_macros>
5006c3fb27SDimitry Andric 
51fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
52fe6060f1SDimitry Andric 
5306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
54fe6060f1SDimitry Andric 
55fe6060f1SDimitry Andric namespace ranges {
56fe6060f1SDimitry Andric template <class _From, class _To>
5704eeddc0SDimitry Andric concept __uses_nonqualification_pointer_conversion =
5804eeddc0SDimitry Andric     is_pointer_v<_From> && is_pointer_v<_To> &&
5904eeddc0SDimitry Andric     !convertible_to<remove_pointer_t<_From> (*)[], remove_pointer_t<_To> (*)[]>;
6004eeddc0SDimitry Andric 
6104eeddc0SDimitry Andric template <class _From, class _To>
62fe6060f1SDimitry Andric concept __convertible_to_non_slicing =
63cb14a3feSDimitry Andric     convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric template <class _Pair, class _Iter, class _Sent>
66fe6060f1SDimitry Andric concept __pair_like_convertible_from =
67*0fca6ea1SDimitry Andric     !range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&
68cb14a3feSDimitry Andric     __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>;
69fe6060f1SDimitry Andric 
70cb14a3feSDimitry Andric template <input_or_output_iterator _Iter,
71cb14a3feSDimitry Andric           sentinel_for<_Iter> _Sent = _Iter,
72cb14a3feSDimitry Andric           subrange_kind _Kind       = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized : subrange_kind::unsized>
73fe6060f1SDimitry Andric   requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>)
74cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sent, _Kind>> {
7581ad6265SDimitry Andric public:
7681ad6265SDimitry Andric   // Note: this is an internal implementation detail that is public only for internal usage.
77349cc55cSDimitry Andric   static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>);
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric private:
80349cc55cSDimitry Andric   static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics
81cb14a3feSDimitry Andric   struct _Empty {
82cb14a3feSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept {}
83cb14a3feSDimitry Andric   };
84349cc55cSDimitry Andric   using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>;
8581ad6265SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter();
8681ad6265SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_   = _Sent();
8781ad6265SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_  = 0;
88fe6060f1SDimitry Andric 
89349cc55cSDimitry Andric public:
90cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI subrange()
91cb14a3feSDimitry Andric     requires default_initializable<_Iter>
92cb14a3feSDimitry Andric   = default;
93fe6060f1SDimitry Andric 
94cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent)
95349cc55cSDimitry Andric     requires _MustProvideSizeAtConstruction
96cb14a3feSDimitry Andric       : __begin_(std::move(__iter)), __end_(std::move(__sent)) {}
97fe6060f1SDimitry Andric 
98cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr subrange(
99cb14a3feSDimitry Andric       __convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> __n)
100fe6060f1SDimitry Andric     requires(_Kind == subrange_kind::sized)
101cb14a3feSDimitry Andric       : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) {
102349cc55cSDimitry Andric     if constexpr (sized_sentinel_for<_Sent, _Iter>)
103cb14a3feSDimitry Andric       _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n),
104349cc55cSDimitry Andric                                           "std::ranges::subrange was passed an invalid size hint");
105349cc55cSDimitry Andric   }
106fe6060f1SDimitry Andric 
107fe6060f1SDimitry Andric   template <__different_from<subrange> _Range>
108cb14a3feSDimitry Andric     requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
109fe6060f1SDimitry Andric              convertible_to<sentinel_t<_Range>, _Sent>
110cb14a3feSDimitry Andric              _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range)
111349cc55cSDimitry Andric                requires(!_StoreSize)
112cb14a3feSDimitry Andric       : subrange(ranges::begin(__range), ranges::end(__range)) {}
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric   template <__different_from<subrange> _Range>
115cb14a3feSDimitry Andric     requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
116fe6060f1SDimitry Andric              convertible_to<sentinel_t<_Range>, _Sent>
117cb14a3feSDimitry Andric              _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range)
118349cc55cSDimitry Andric                requires _StoreSize && sized_range<_Range>
119cb14a3feSDimitry Andric       : subrange(__range, ranges::size(__range)) {}
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric   template <borrowed_range _Range>
122fe6060f1SDimitry Andric     requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
123fe6060f1SDimitry Andric              convertible_to<sentinel_t<_Range>, _Sent>
124cb14a3feSDimitry Andric              _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n)
125fe6060f1SDimitry Andric                requires(_Kind == subrange_kind::sized)
126cb14a3feSDimitry Andric       : subrange(ranges::begin(__range), ranges::end(__range), __n) {}
127fe6060f1SDimitry Andric 
128*0fca6ea1SDimitry Andric   template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair>
129cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const {
130349cc55cSDimitry Andric     return _Pair(__begin_, __end_);
131349cc55cSDimitry Andric   }
132fe6060f1SDimitry Andric 
133cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const
134cb14a3feSDimitry Andric     requires copyable<_Iter>
135cb14a3feSDimitry Andric   {
136349cc55cSDimitry Andric     return __begin_;
137fe6060f1SDimitry Andric   }
138fe6060f1SDimitry Andric 
139cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin()
140cb14a3feSDimitry Andric     requires(!copyable<_Iter>)
141cb14a3feSDimitry Andric   {
14281ad6265SDimitry Andric     return std::move(__begin_);
143fe6060f1SDimitry Andric   }
144fe6060f1SDimitry Andric 
145cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; }
146fe6060f1SDimitry Andric 
147cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __begin_ == __end_; }
148fe6060f1SDimitry Andric 
149cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
150fe6060f1SDimitry Andric     requires(_Kind == subrange_kind::sized)
151fe6060f1SDimitry Andric   {
152349cc55cSDimitry Andric     if constexpr (_StoreSize)
153349cc55cSDimitry Andric       return __size_;
154fe6060f1SDimitry Andric     else
15581ad6265SDimitry Andric       return std::__to_unsigned_like(__end_ - __begin_);
156fe6060f1SDimitry Andric   }
157fe6060f1SDimitry Andric 
158fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const&
159349cc55cSDimitry Andric     requires forward_iterator<_Iter>
160349cc55cSDimitry Andric   {
161fe6060f1SDimitry Andric     auto __tmp = *this;
162fe6060f1SDimitry Andric     __tmp.advance(__n);
163fe6060f1SDimitry Andric     return __tmp;
164fe6060f1SDimitry Andric   }
165fe6060f1SDimitry Andric 
166fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && {
167fe6060f1SDimitry Andric     advance(__n);
16881ad6265SDimitry Andric     return std::move(*this);
169fe6060f1SDimitry Andric   }
170fe6060f1SDimitry Andric 
171fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const
172349cc55cSDimitry Andric     requires bidirectional_iterator<_Iter>
173349cc55cSDimitry Andric   {
174fe6060f1SDimitry Andric     auto __tmp = *this;
175fe6060f1SDimitry Andric     __tmp.advance(-__n);
176fe6060f1SDimitry Andric     return __tmp;
177fe6060f1SDimitry Andric   }
178fe6060f1SDimitry Andric 
179cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr subrange& advance(iter_difference_t<_Iter> __n) {
180fe6060f1SDimitry Andric     if constexpr (bidirectional_iterator<_Iter>) {
181fe6060f1SDimitry Andric       if (__n < 0) {
182349cc55cSDimitry Andric         ranges::advance(__begin_, __n);
183349cc55cSDimitry Andric         if constexpr (_StoreSize)
18481ad6265SDimitry Andric           __size_ += std::__to_unsigned_like(-__n);
185fe6060f1SDimitry Andric         return *this;
186fe6060f1SDimitry Andric       }
187fe6060f1SDimitry Andric     }
188fe6060f1SDimitry Andric 
189349cc55cSDimitry Andric     auto __d = __n - ranges::advance(__begin_, __n, __end_);
190349cc55cSDimitry Andric     if constexpr (_StoreSize)
19181ad6265SDimitry Andric       __size_ -= std::__to_unsigned_like(__d);
192fe6060f1SDimitry Andric     return *this;
193fe6060f1SDimitry Andric   }
194fe6060f1SDimitry Andric };
195fe6060f1SDimitry Andric 
196fe6060f1SDimitry Andric template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
197fe6060f1SDimitry Andric subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;
198fe6060f1SDimitry Andric 
199fe6060f1SDimitry Andric template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
200cb14a3feSDimitry Andric subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) -> subrange<_Iter, _Sent, subrange_kind::sized>;
201fe6060f1SDimitry Andric 
202fe6060f1SDimitry Andric template <borrowed_range _Range>
203*0fca6ea1SDimitry Andric subrange(_Range&&) -> subrange<iterator_t<_Range>,
204cb14a3feSDimitry Andric                                sentinel_t<_Range>,
205fe6060f1SDimitry Andric                                (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>)
206cb14a3feSDimitry Andric                                    ? subrange_kind::sized
207cb14a3feSDimitry Andric                                    : subrange_kind::unsized>;
208fe6060f1SDimitry Andric 
209fe6060f1SDimitry Andric template <borrowed_range _Range>
210fe6060f1SDimitry Andric subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)
211fe6060f1SDimitry Andric     -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;
212fe6060f1SDimitry Andric 
213fe6060f1SDimitry Andric template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
2141fd87a68SDimitry Andric   requires((_Index == 0 && copyable<_Iter>) || _Index == 1)
215cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
216fe6060f1SDimitry Andric   if constexpr (_Index == 0)
217fe6060f1SDimitry Andric     return __subrange.begin();
218fe6060f1SDimitry Andric   else
219fe6060f1SDimitry Andric     return __subrange.end();
220fe6060f1SDimitry Andric }
221fe6060f1SDimitry Andric 
222fe6060f1SDimitry Andric template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
223fe6060f1SDimitry Andric   requires(_Index < 2)
224cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
225fe6060f1SDimitry Andric   if constexpr (_Index == 0)
226fe6060f1SDimitry Andric     return __subrange.begin();
227fe6060f1SDimitry Andric   else
228fe6060f1SDimitry Andric     return __subrange.end();
229fe6060f1SDimitry Andric }
230fe6060f1SDimitry Andric 
231fe6060f1SDimitry Andric template <class _Ip, class _Sp, subrange_kind _Kp>
232fe6060f1SDimitry Andric inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;
233fe6060f1SDimitry Andric 
234fe6060f1SDimitry Andric template <range _Rp>
235fe6060f1SDimitry Andric using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>;
236fe6060f1SDimitry Andric } // namespace ranges
237fe6060f1SDimitry Andric 
238349cc55cSDimitry Andric // [range.subrange.general]
239349cc55cSDimitry Andric 
240fe6060f1SDimitry Andric using ranges::get;
241fe6060f1SDimitry Andric 
242349cc55cSDimitry Andric // [ranges.syn]
243349cc55cSDimitry Andric 
244349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
245349cc55cSDimitry Andric struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {};
246349cc55cSDimitry Andric 
247349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
248349cc55cSDimitry Andric struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
249349cc55cSDimitry Andric   using type = _Ip;
250349cc55cSDimitry Andric };
251349cc55cSDimitry Andric 
252349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
253349cc55cSDimitry Andric struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
254349cc55cSDimitry Andric   using type = _Sp;
255349cc55cSDimitry Andric };
256349cc55cSDimitry Andric 
257349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
258349cc55cSDimitry Andric struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> {
259349cc55cSDimitry Andric   using type = _Ip;
260349cc55cSDimitry Andric };
261349cc55cSDimitry Andric 
262349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
263349cc55cSDimitry Andric struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> {
264349cc55cSDimitry Andric   using type = _Sp;
265349cc55cSDimitry Andric };
266fe6060f1SDimitry Andric 
26706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
268fe6060f1SDimitry Andric 
269fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
270fe6060f1SDimitry Andric 
27106c3fb27SDimitry Andric _LIBCPP_POP_MACROS
27206c3fb27SDimitry Andric 
273fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_SUBRANGE_H
274