176d0caaeSpatrick // -*- C++ -*-
276d0caaeSpatrick //===----------------------------------------------------------------------===//
376d0caaeSpatrick //
476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information.
676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
776d0caaeSpatrick //
876d0caaeSpatrick //===----------------------------------------------------------------------===//
9*4bdff4beSrobert 
1076d0caaeSpatrick #ifndef _LIBCPP___RANGES_SUBRANGE_H
1176d0caaeSpatrick #define _LIBCPP___RANGES_SUBRANGE_H
1276d0caaeSpatrick 
13*4bdff4beSrobert #include <__assert>
14*4bdff4beSrobert #include <__concepts/constructible.h>
15*4bdff4beSrobert #include <__concepts/convertible_to.h>
16*4bdff4beSrobert #include <__concepts/copyable.h>
17*4bdff4beSrobert #include <__concepts/derived_from.h>
18*4bdff4beSrobert #include <__concepts/different_from.h>
1976d0caaeSpatrick #include <__config>
20*4bdff4beSrobert #include <__fwd/get.h>
21*4bdff4beSrobert #include <__fwd/subrange.h>
22*4bdff4beSrobert #include <__iterator/advance.h>
2376d0caaeSpatrick #include <__iterator/concepts.h>
2476d0caaeSpatrick #include <__iterator/incrementable_traits.h>
2576d0caaeSpatrick #include <__iterator/iterator_traits.h>
2676d0caaeSpatrick #include <__ranges/access.h>
2776d0caaeSpatrick #include <__ranges/concepts.h>
2876d0caaeSpatrick #include <__ranges/dangling.h>
2976d0caaeSpatrick #include <__ranges/enable_borrowed_range.h>
3076d0caaeSpatrick #include <__ranges/size.h>
3176d0caaeSpatrick #include <__ranges/view_interface.h>
32*4bdff4beSrobert #include <__tuple_dir/pair_like.h>
33*4bdff4beSrobert #include <__tuple_dir/tuple_element.h>
34*4bdff4beSrobert #include <__tuple_dir/tuple_size.h>
35*4bdff4beSrobert #include <__type_traits/conditional.h>
36*4bdff4beSrobert #include <__type_traits/decay.h>
37*4bdff4beSrobert #include <__type_traits/is_pointer.h>
38*4bdff4beSrobert #include <__type_traits/is_reference.h>
39*4bdff4beSrobert #include <__type_traits/make_unsigned.h>
40*4bdff4beSrobert #include <__type_traits/remove_const.h>
41*4bdff4beSrobert #include <__type_traits/remove_pointer.h>
42*4bdff4beSrobert #include <__utility/move.h>
43*4bdff4beSrobert #include <cstddef>
4476d0caaeSpatrick 
4576d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
4676d0caaeSpatrick #  pragma GCC system_header
4776d0caaeSpatrick #endif
4876d0caaeSpatrick 
4976d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD
5076d0caaeSpatrick 
51*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
5276d0caaeSpatrick 
5376d0caaeSpatrick namespace ranges {
5476d0caaeSpatrick   template<class _From, class _To>
55*4bdff4beSrobert   concept __uses_nonqualification_pointer_conversion =
56*4bdff4beSrobert     is_pointer_v<_From> && is_pointer_v<_To> &&
57*4bdff4beSrobert     !convertible_to<remove_pointer_t<_From>(*)[], remove_pointer_t<_To>(*)[]>;
58*4bdff4beSrobert 
59*4bdff4beSrobert   template<class _From, class _To>
6076d0caaeSpatrick   concept __convertible_to_non_slicing =
6176d0caaeSpatrick     convertible_to<_From, _To> &&
62*4bdff4beSrobert     !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;
6376d0caaeSpatrick 
6476d0caaeSpatrick   template<class _Pair, class _Iter, class _Sent>
6576d0caaeSpatrick   concept __pair_like_convertible_from =
6676d0caaeSpatrick     !range<_Pair> && __pair_like<_Pair> &&
6776d0caaeSpatrick     constructible_from<_Pair, _Iter, _Sent> &&
6876d0caaeSpatrick     __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> &&
6976d0caaeSpatrick     convertible_to<_Sent, tuple_element_t<1, _Pair>>;
7076d0caaeSpatrick 
7176d0caaeSpatrick   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter,
7276d0caaeSpatrick            subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter>
7376d0caaeSpatrick              ? subrange_kind::sized
7476d0caaeSpatrick              : subrange_kind::unsized>
7576d0caaeSpatrick     requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>)
76*4bdff4beSrobert   class _LIBCPP_TEMPLATE_VIS subrange
77*4bdff4beSrobert     : public view_interface<subrange<_Iter, _Sent, _Kind>>
78*4bdff4beSrobert   {
79*4bdff4beSrobert   public:
80*4bdff4beSrobert     // Note: this is an internal implementation detail that is public only for internal usage.
81*4bdff4beSrobert     static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>);
8276d0caaeSpatrick 
83*4bdff4beSrobert   private:
84*4bdff4beSrobert     static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics
_Empty_Empty85*4bdff4beSrobert     struct _Empty { constexpr _Empty(auto) noexcept { } };
86*4bdff4beSrobert     using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>;
87*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter();
88*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent();
89*4bdff4beSrobert     _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0;
9076d0caaeSpatrick 
91*4bdff4beSrobert   public:
9276d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
9376d0caaeSpatrick     subrange() requires default_initializable<_Iter> = default;
9476d0caaeSpatrick 
9576d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
subrange(__convertible_to_non_slicing<_Iter> auto __iter,_Sent __sent)9676d0caaeSpatrick     constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent)
97*4bdff4beSrobert       requires _MustProvideSizeAtConstruction
98*4bdff4beSrobert       : __begin_(std::move(__iter)), __end_(std::move(__sent))
99*4bdff4beSrobert     { }
10076d0caaeSpatrick 
10176d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
subrange(__convertible_to_non_slicing<_Iter> auto __iter,_Sent __sent,make_unsigned_t<iter_difference_t<_Iter>> __n)10276d0caaeSpatrick     constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent,
10376d0caaeSpatrick                        make_unsigned_t<iter_difference_t<_Iter>> __n)
10476d0caaeSpatrick       requires (_Kind == subrange_kind::sized)
105*4bdff4beSrobert       : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n)
106*4bdff4beSrobert     {
107*4bdff4beSrobert       if constexpr (sized_sentinel_for<_Sent, _Iter>)
108*4bdff4beSrobert         _LIBCPP_ASSERT((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n),
109*4bdff4beSrobert           "std::ranges::subrange was passed an invalid size hint");
110*4bdff4beSrobert     }
11176d0caaeSpatrick 
11276d0caaeSpatrick     template<__different_from<subrange> _Range>
11376d0caaeSpatrick       requires borrowed_range<_Range> &&
11476d0caaeSpatrick                __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
11576d0caaeSpatrick                convertible_to<sentinel_t<_Range>, _Sent>
11676d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
subrange(_Range && __range)11776d0caaeSpatrick     constexpr subrange(_Range&& __range)
118*4bdff4beSrobert       requires (!_StoreSize)
119*4bdff4beSrobert       : subrange(ranges::begin(__range), ranges::end(__range))
120*4bdff4beSrobert     { }
12176d0caaeSpatrick 
12276d0caaeSpatrick     template<__different_from<subrange> _Range>
12376d0caaeSpatrick       requires borrowed_range<_Range> &&
12476d0caaeSpatrick                __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
12576d0caaeSpatrick                convertible_to<sentinel_t<_Range>, _Sent>
12676d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
subrange(_Range && __range)12776d0caaeSpatrick     constexpr subrange(_Range&& __range)
128*4bdff4beSrobert       requires _StoreSize && sized_range<_Range>
129*4bdff4beSrobert       : subrange(__range, ranges::size(__range))
130*4bdff4beSrobert     { }
13176d0caaeSpatrick 
13276d0caaeSpatrick     template<borrowed_range _Range>
13376d0caaeSpatrick       requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
13476d0caaeSpatrick                convertible_to<sentinel_t<_Range>, _Sent>
13576d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
subrange(_Range && __range,make_unsigned_t<iter_difference_t<_Iter>> __n)13676d0caaeSpatrick     constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n)
13776d0caaeSpatrick       requires (_Kind == subrange_kind::sized)
138*4bdff4beSrobert       : subrange(ranges::begin(__range), ranges::end(__range), __n)
139*4bdff4beSrobert     { }
14076d0caaeSpatrick 
14176d0caaeSpatrick     template<__different_from<subrange> _Pair>
14276d0caaeSpatrick       requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
14376d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
_Pair()144*4bdff4beSrobert     constexpr operator _Pair() const {
145*4bdff4beSrobert       return _Pair(__begin_, __end_);
146*4bdff4beSrobert     }
14776d0caaeSpatrick 
14876d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
begin()14976d0caaeSpatrick     constexpr _Iter begin() const requires copyable<_Iter> {
150*4bdff4beSrobert       return __begin_;
15176d0caaeSpatrick     }
15276d0caaeSpatrick 
begin()15376d0caaeSpatrick     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) {
154*4bdff4beSrobert       return std::move(__begin_);
15576d0caaeSpatrick     }
15676d0caaeSpatrick 
15776d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
end()158*4bdff4beSrobert     constexpr _Sent end() const {
159*4bdff4beSrobert       return __end_;
160*4bdff4beSrobert     }
16176d0caaeSpatrick 
empty()162*4bdff4beSrobert     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const {
163*4bdff4beSrobert       return __begin_ == __end_;
164*4bdff4beSrobert     }
16576d0caaeSpatrick 
16676d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
size()16776d0caaeSpatrick     constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
16876d0caaeSpatrick       requires (_Kind == subrange_kind::sized)
16976d0caaeSpatrick     {
170*4bdff4beSrobert       if constexpr (_StoreSize)
171*4bdff4beSrobert         return __size_;
17276d0caaeSpatrick       else
173*4bdff4beSrobert         return std::__to_unsigned_like(__end_ - __begin_);
17476d0caaeSpatrick     }
17576d0caaeSpatrick 
17676d0caaeSpatrick     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const&
177*4bdff4beSrobert       requires forward_iterator<_Iter>
178*4bdff4beSrobert     {
17976d0caaeSpatrick       auto __tmp = *this;
18076d0caaeSpatrick       __tmp.advance(__n);
18176d0caaeSpatrick       return __tmp;
18276d0caaeSpatrick     }
18376d0caaeSpatrick 
18476d0caaeSpatrick     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && {
18576d0caaeSpatrick       advance(__n);
186*4bdff4beSrobert       return std::move(*this);
18776d0caaeSpatrick     }
18876d0caaeSpatrick 
18976d0caaeSpatrick     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const
190*4bdff4beSrobert       requires bidirectional_iterator<_Iter>
191*4bdff4beSrobert     {
19276d0caaeSpatrick       auto __tmp = *this;
19376d0caaeSpatrick       __tmp.advance(-__n);
19476d0caaeSpatrick       return __tmp;
19576d0caaeSpatrick     }
19676d0caaeSpatrick 
19776d0caaeSpatrick     _LIBCPP_HIDE_FROM_ABI
advance(iter_difference_t<_Iter> __n)19876d0caaeSpatrick     constexpr subrange& advance(iter_difference_t<_Iter> __n) {
19976d0caaeSpatrick       if constexpr (bidirectional_iterator<_Iter>) {
20076d0caaeSpatrick         if (__n < 0) {
201*4bdff4beSrobert           ranges::advance(__begin_, __n);
202*4bdff4beSrobert           if constexpr (_StoreSize)
203*4bdff4beSrobert             __size_ += std::__to_unsigned_like(-__n);
20476d0caaeSpatrick           return *this;
20576d0caaeSpatrick         }
20676d0caaeSpatrick       }
20776d0caaeSpatrick 
208*4bdff4beSrobert       auto __d = __n - ranges::advance(__begin_, __n, __end_);
209*4bdff4beSrobert       if constexpr (_StoreSize)
210*4bdff4beSrobert         __size_ -= std::__to_unsigned_like(__d);
21176d0caaeSpatrick       return *this;
21276d0caaeSpatrick     }
21376d0caaeSpatrick   };
21476d0caaeSpatrick 
21576d0caaeSpatrick   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
21676d0caaeSpatrick   subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;
21776d0caaeSpatrick 
21876d0caaeSpatrick   template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
21976d0caaeSpatrick   subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>)
22076d0caaeSpatrick     -> subrange<_Iter, _Sent, subrange_kind::sized>;
22176d0caaeSpatrick 
22276d0caaeSpatrick   template<borrowed_range _Range>
22376d0caaeSpatrick   subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>,
22476d0caaeSpatrick                                  (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>)
22576d0caaeSpatrick                                    ? subrange_kind::sized : subrange_kind::unsized>;
22676d0caaeSpatrick 
22776d0caaeSpatrick   template<borrowed_range _Range>
22876d0caaeSpatrick   subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)
22976d0caaeSpatrick     -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;
23076d0caaeSpatrick 
23176d0caaeSpatrick   template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
232*4bdff4beSrobert     requires ((_Index == 0 && copyable<_Iter>) || _Index == 1)
23376d0caaeSpatrick   _LIBCPP_HIDE_FROM_ABI
get(const subrange<_Iter,_Sent,_Kind> & __subrange)23476d0caaeSpatrick   constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
23576d0caaeSpatrick     if constexpr (_Index == 0)
23676d0caaeSpatrick       return __subrange.begin();
23776d0caaeSpatrick     else
23876d0caaeSpatrick       return __subrange.end();
23976d0caaeSpatrick   }
24076d0caaeSpatrick 
24176d0caaeSpatrick   template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
24276d0caaeSpatrick     requires (_Index < 2)
24376d0caaeSpatrick   _LIBCPP_HIDE_FROM_ABI
get(subrange<_Iter,_Sent,_Kind> && __subrange)24476d0caaeSpatrick   constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
24576d0caaeSpatrick     if constexpr (_Index == 0)
24676d0caaeSpatrick       return __subrange.begin();
24776d0caaeSpatrick     else
24876d0caaeSpatrick       return __subrange.end();
24976d0caaeSpatrick   }
25076d0caaeSpatrick 
25176d0caaeSpatrick   template<class _Ip, class _Sp, subrange_kind _Kp>
25276d0caaeSpatrick   inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;
25376d0caaeSpatrick 
25476d0caaeSpatrick   template<range _Rp>
25576d0caaeSpatrick   using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>;
25676d0caaeSpatrick } // namespace ranges
25776d0caaeSpatrick 
258*4bdff4beSrobert // [range.subrange.general]
259*4bdff4beSrobert 
26076d0caaeSpatrick using ranges::get;
26176d0caaeSpatrick 
262*4bdff4beSrobert // [ranges.syn]
26376d0caaeSpatrick 
264*4bdff4beSrobert template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
265*4bdff4beSrobert struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {};
266*4bdff4beSrobert 
267*4bdff4beSrobert template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
268*4bdff4beSrobert struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
269*4bdff4beSrobert   using type = _Ip;
270*4bdff4beSrobert };
271*4bdff4beSrobert 
272*4bdff4beSrobert template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
273*4bdff4beSrobert struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
274*4bdff4beSrobert   using type = _Sp;
275*4bdff4beSrobert };
276*4bdff4beSrobert 
277*4bdff4beSrobert template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
278*4bdff4beSrobert struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> {
279*4bdff4beSrobert   using type = _Ip;
280*4bdff4beSrobert };
281*4bdff4beSrobert 
282*4bdff4beSrobert template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
283*4bdff4beSrobert struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> {
284*4bdff4beSrobert   using type = _Sp;
285*4bdff4beSrobert };
286*4bdff4beSrobert 
287*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
28876d0caaeSpatrick 
28976d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD
29076d0caaeSpatrick 
29176d0caaeSpatrick #endif // _LIBCPP___RANGES_SUBRANGE_H
292