xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/subrange.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 //===----------------------------------------------------------------------===//
9*bdd1243dSDimitry 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>
20*bdd1243dSDimitry Andric #include <__fwd/get.h>
21*bdd1243dSDimitry Andric #include <__fwd/subrange.h>
22349cc55cSDimitry Andric #include <__iterator/advance.h>
23fe6060f1SDimitry Andric #include <__iterator/concepts.h>
24fe6060f1SDimitry Andric #include <__iterator/incrementable_traits.h>
25fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
26fe6060f1SDimitry Andric #include <__ranges/access.h>
27fe6060f1SDimitry Andric #include <__ranges/concepts.h>
28fe6060f1SDimitry Andric #include <__ranges/dangling.h>
29fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h>
30fe6060f1SDimitry Andric #include <__ranges/size.h>
31fe6060f1SDimitry Andric #include <__ranges/view_interface.h>
32*bdd1243dSDimitry Andric #include <__tuple_dir/pair_like.h>
33*bdd1243dSDimitry Andric #include <__tuple_dir/tuple_element.h>
34*bdd1243dSDimitry Andric #include <__tuple_dir/tuple_size.h>
35*bdd1243dSDimitry Andric #include <__type_traits/conditional.h>
36*bdd1243dSDimitry Andric #include <__type_traits/decay.h>
37*bdd1243dSDimitry Andric #include <__type_traits/is_pointer.h>
38*bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
39*bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h>
40*bdd1243dSDimitry Andric #include <__type_traits/remove_const.h>
41*bdd1243dSDimitry Andric #include <__type_traits/remove_pointer.h>
42349cc55cSDimitry Andric #include <__utility/move.h>
43*bdd1243dSDimitry Andric #include <cstddef>
44fe6060f1SDimitry Andric 
45fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
46fe6060f1SDimitry Andric #  pragma GCC system_header
47fe6060f1SDimitry Andric #endif
48fe6060f1SDimitry Andric 
49fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
50fe6060f1SDimitry Andric 
51*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
52fe6060f1SDimitry Andric 
53fe6060f1SDimitry Andric namespace ranges {
54fe6060f1SDimitry Andric   template<class _From, class _To>
5504eeddc0SDimitry Andric   concept __uses_nonqualification_pointer_conversion =
5604eeddc0SDimitry Andric     is_pointer_v<_From> && is_pointer_v<_To> &&
5704eeddc0SDimitry Andric     !convertible_to<remove_pointer_t<_From>(*)[], remove_pointer_t<_To>(*)[]>;
5804eeddc0SDimitry Andric 
5904eeddc0SDimitry Andric   template<class _From, class _To>
60fe6060f1SDimitry Andric   concept __convertible_to_non_slicing =
61fe6060f1SDimitry Andric     convertible_to<_From, _To> &&
6204eeddc0SDimitry Andric     !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;
63fe6060f1SDimitry Andric 
64fe6060f1SDimitry Andric   template<class _Pair, class _Iter, class _Sent>
65fe6060f1SDimitry Andric   concept __pair_like_convertible_from =
66fe6060f1SDimitry Andric     !range<_Pair> && __pair_like<_Pair> &&
67fe6060f1SDimitry Andric     constructible_from<_Pair, _Iter, _Sent> &&
68fe6060f1SDimitry Andric     __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> &&
69fe6060f1SDimitry Andric     convertible_to<_Sent, tuple_element_t<1, _Pair>>;
70fe6060f1SDimitry Andric 
71fe6060f1SDimitry Andric   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter,
72fe6060f1SDimitry Andric            subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter>
73fe6060f1SDimitry Andric              ? subrange_kind::sized
74fe6060f1SDimitry Andric              : subrange_kind::unsized>
75fe6060f1SDimitry Andric     requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>)
76349cc55cSDimitry Andric   class _LIBCPP_TEMPLATE_VIS subrange
77349cc55cSDimitry Andric     : public view_interface<subrange<_Iter, _Sent, _Kind>>
78349cc55cSDimitry Andric   {
7981ad6265SDimitry Andric   public:
8081ad6265SDimitry Andric     // Note: this is an internal implementation detail that is public only for internal usage.
81349cc55cSDimitry Andric     static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>);
8281ad6265SDimitry Andric 
8381ad6265SDimitry Andric   private:
84349cc55cSDimitry Andric     static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics
85349cc55cSDimitry Andric     struct _Empty { constexpr _Empty(auto) noexcept { } };
86349cc55cSDimitry Andric     using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>;
8781ad6265SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter();
8881ad6265SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent();
8981ad6265SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0;
90fe6060f1SDimitry Andric 
91349cc55cSDimitry Andric   public:
92fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
93fe6060f1SDimitry Andric     subrange() requires default_initializable<_Iter> = default;
94fe6060f1SDimitry Andric 
95fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
96fe6060f1SDimitry Andric     constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent)
97349cc55cSDimitry Andric       requires _MustProvideSizeAtConstruction
9881ad6265SDimitry Andric       : __begin_(std::move(__iter)), __end_(std::move(__sent))
99349cc55cSDimitry Andric     { }
100fe6060f1SDimitry Andric 
101fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
102fe6060f1SDimitry Andric     constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent,
103fe6060f1SDimitry Andric                        make_unsigned_t<iter_difference_t<_Iter>> __n)
104fe6060f1SDimitry Andric       requires (_Kind == subrange_kind::sized)
10581ad6265SDimitry Andric       : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n)
106349cc55cSDimitry Andric     {
107349cc55cSDimitry Andric       if constexpr (sized_sentinel_for<_Sent, _Iter>)
108349cc55cSDimitry Andric         _LIBCPP_ASSERT((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n),
109349cc55cSDimitry Andric           "std::ranges::subrange was passed an invalid size hint");
110349cc55cSDimitry Andric     }
111fe6060f1SDimitry Andric 
112fe6060f1SDimitry Andric     template<__different_from<subrange> _Range>
113fe6060f1SDimitry Andric       requires borrowed_range<_Range> &&
114fe6060f1SDimitry Andric                __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
115fe6060f1SDimitry Andric                convertible_to<sentinel_t<_Range>, _Sent>
116fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
117fe6060f1SDimitry Andric     constexpr subrange(_Range&& __range)
118349cc55cSDimitry Andric       requires (!_StoreSize)
119349cc55cSDimitry Andric       : subrange(ranges::begin(__range), ranges::end(__range))
120349cc55cSDimitry Andric     { }
121fe6060f1SDimitry Andric 
122fe6060f1SDimitry Andric     template<__different_from<subrange> _Range>
123fe6060f1SDimitry Andric       requires borrowed_range<_Range> &&
124fe6060f1SDimitry Andric                __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
125fe6060f1SDimitry Andric                convertible_to<sentinel_t<_Range>, _Sent>
126fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
127fe6060f1SDimitry Andric     constexpr subrange(_Range&& __range)
128349cc55cSDimitry Andric       requires _StoreSize && sized_range<_Range>
129349cc55cSDimitry Andric       : subrange(__range, ranges::size(__range))
130349cc55cSDimitry Andric     { }
131fe6060f1SDimitry Andric 
132fe6060f1SDimitry Andric     template<borrowed_range _Range>
133fe6060f1SDimitry Andric       requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
134fe6060f1SDimitry Andric                convertible_to<sentinel_t<_Range>, _Sent>
135fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
136fe6060f1SDimitry Andric     constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n)
137fe6060f1SDimitry Andric       requires (_Kind == subrange_kind::sized)
138349cc55cSDimitry Andric       : subrange(ranges::begin(__range), ranges::end(__range), __n)
139349cc55cSDimitry Andric     { }
140fe6060f1SDimitry Andric 
141fe6060f1SDimitry Andric     template<__different_from<subrange> _Pair>
142fe6060f1SDimitry Andric       requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
143fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
144349cc55cSDimitry Andric     constexpr operator _Pair() const {
145349cc55cSDimitry Andric       return _Pair(__begin_, __end_);
146349cc55cSDimitry Andric     }
147fe6060f1SDimitry Andric 
148fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
149fe6060f1SDimitry Andric     constexpr _Iter begin() const requires copyable<_Iter> {
150349cc55cSDimitry Andric       return __begin_;
151fe6060f1SDimitry Andric     }
152fe6060f1SDimitry Andric 
153fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) {
15481ad6265SDimitry Andric       return std::move(__begin_);
155fe6060f1SDimitry Andric     }
156fe6060f1SDimitry Andric 
157fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
158349cc55cSDimitry Andric     constexpr _Sent end() const {
159349cc55cSDimitry Andric       return __end_;
160349cc55cSDimitry Andric     }
161fe6060f1SDimitry Andric 
162349cc55cSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const {
163349cc55cSDimitry Andric       return __begin_ == __end_;
164349cc55cSDimitry Andric     }
165fe6060f1SDimitry Andric 
166fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
167fe6060f1SDimitry Andric     constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
168fe6060f1SDimitry Andric       requires (_Kind == subrange_kind::sized)
169fe6060f1SDimitry Andric     {
170349cc55cSDimitry Andric       if constexpr (_StoreSize)
171349cc55cSDimitry Andric         return __size_;
172fe6060f1SDimitry Andric       else
17381ad6265SDimitry Andric         return std::__to_unsigned_like(__end_ - __begin_);
174fe6060f1SDimitry Andric     }
175fe6060f1SDimitry Andric 
176fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const&
177349cc55cSDimitry Andric       requires forward_iterator<_Iter>
178349cc55cSDimitry Andric     {
179fe6060f1SDimitry Andric       auto __tmp = *this;
180fe6060f1SDimitry Andric       __tmp.advance(__n);
181fe6060f1SDimitry Andric       return __tmp;
182fe6060f1SDimitry Andric     }
183fe6060f1SDimitry Andric 
184fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && {
185fe6060f1SDimitry Andric       advance(__n);
18681ad6265SDimitry Andric       return std::move(*this);
187fe6060f1SDimitry Andric     }
188fe6060f1SDimitry Andric 
189fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const
190349cc55cSDimitry Andric       requires bidirectional_iterator<_Iter>
191349cc55cSDimitry Andric     {
192fe6060f1SDimitry Andric       auto __tmp = *this;
193fe6060f1SDimitry Andric       __tmp.advance(-__n);
194fe6060f1SDimitry Andric       return __tmp;
195fe6060f1SDimitry Andric     }
196fe6060f1SDimitry Andric 
197fe6060f1SDimitry Andric     _LIBCPP_HIDE_FROM_ABI
198fe6060f1SDimitry Andric     constexpr subrange& advance(iter_difference_t<_Iter> __n) {
199fe6060f1SDimitry Andric       if constexpr (bidirectional_iterator<_Iter>) {
200fe6060f1SDimitry Andric         if (__n < 0) {
201349cc55cSDimitry Andric           ranges::advance(__begin_, __n);
202349cc55cSDimitry Andric           if constexpr (_StoreSize)
20381ad6265SDimitry Andric             __size_ += std::__to_unsigned_like(-__n);
204fe6060f1SDimitry Andric           return *this;
205fe6060f1SDimitry Andric         }
206fe6060f1SDimitry Andric       }
207fe6060f1SDimitry Andric 
208349cc55cSDimitry Andric       auto __d = __n - ranges::advance(__begin_, __n, __end_);
209349cc55cSDimitry Andric       if constexpr (_StoreSize)
21081ad6265SDimitry Andric         __size_ -= std::__to_unsigned_like(__d);
211fe6060f1SDimitry Andric       return *this;
212fe6060f1SDimitry Andric     }
213fe6060f1SDimitry Andric   };
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
216fe6060f1SDimitry Andric   subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;
217fe6060f1SDimitry Andric 
218fe6060f1SDimitry Andric   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
219fe6060f1SDimitry Andric   subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>)
220fe6060f1SDimitry Andric     -> subrange<_Iter, _Sent, subrange_kind::sized>;
221fe6060f1SDimitry Andric 
222fe6060f1SDimitry Andric   template<borrowed_range _Range>
223fe6060f1SDimitry Andric   subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>,
224fe6060f1SDimitry Andric                                  (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>)
225fe6060f1SDimitry Andric                                    ? subrange_kind::sized : subrange_kind::unsized>;
226fe6060f1SDimitry Andric 
227fe6060f1SDimitry Andric   template<borrowed_range _Range>
228fe6060f1SDimitry Andric   subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)
229fe6060f1SDimitry Andric     -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;
230fe6060f1SDimitry Andric 
231fe6060f1SDimitry Andric   template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
2321fd87a68SDimitry Andric     requires ((_Index == 0 && copyable<_Iter>) || _Index == 1)
233fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
234fe6060f1SDimitry Andric   constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
235fe6060f1SDimitry Andric     if constexpr (_Index == 0)
236fe6060f1SDimitry Andric       return __subrange.begin();
237fe6060f1SDimitry Andric     else
238fe6060f1SDimitry Andric       return __subrange.end();
239fe6060f1SDimitry Andric   }
240fe6060f1SDimitry Andric 
241fe6060f1SDimitry Andric   template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
242fe6060f1SDimitry Andric     requires (_Index < 2)
243fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
244fe6060f1SDimitry Andric   constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
245fe6060f1SDimitry Andric     if constexpr (_Index == 0)
246fe6060f1SDimitry Andric       return __subrange.begin();
247fe6060f1SDimitry Andric     else
248fe6060f1SDimitry Andric       return __subrange.end();
249fe6060f1SDimitry Andric   }
250fe6060f1SDimitry Andric 
251fe6060f1SDimitry Andric   template<class _Ip, class _Sp, subrange_kind _Kp>
252fe6060f1SDimitry Andric   inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;
253fe6060f1SDimitry Andric 
254fe6060f1SDimitry Andric   template<range _Rp>
255fe6060f1SDimitry Andric   using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>;
256fe6060f1SDimitry Andric } // namespace ranges
257fe6060f1SDimitry Andric 
258349cc55cSDimitry Andric // [range.subrange.general]
259349cc55cSDimitry Andric 
260fe6060f1SDimitry Andric using ranges::get;
261fe6060f1SDimitry Andric 
262349cc55cSDimitry Andric // [ranges.syn]
263349cc55cSDimitry Andric 
264349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
265349cc55cSDimitry Andric struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {};
266349cc55cSDimitry Andric 
267349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
268349cc55cSDimitry Andric struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
269349cc55cSDimitry Andric   using type = _Ip;
270349cc55cSDimitry Andric };
271349cc55cSDimitry Andric 
272349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
273349cc55cSDimitry Andric struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
274349cc55cSDimitry Andric   using type = _Sp;
275349cc55cSDimitry Andric };
276349cc55cSDimitry Andric 
277349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
278349cc55cSDimitry Andric struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> {
279349cc55cSDimitry Andric   using type = _Ip;
280349cc55cSDimitry Andric };
281349cc55cSDimitry Andric 
282349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
283349cc55cSDimitry Andric struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> {
284349cc55cSDimitry Andric   using type = _Sp;
285349cc55cSDimitry Andric };
286fe6060f1SDimitry Andric 
287*bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER > 17
288fe6060f1SDimitry Andric 
289fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
290fe6060f1SDimitry Andric 
291fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_SUBRANGE_H
292