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