|  | // -*- C++ -*- | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | #ifndef _LIBCPP___RANGES_SUBRANGE_H | 
|  | #define _LIBCPP___RANGES_SUBRANGE_H | 
|  |  | 
|  | #include <__config> | 
|  | #include <__iterator/concepts.h> | 
|  | #include <__iterator/incrementable_traits.h> | 
|  | #include <__iterator/iterator_traits.h> | 
|  | #include <__iterator/advance.h> | 
|  | #include <__ranges/access.h> | 
|  | #include <__ranges/concepts.h> | 
|  | #include <__ranges/dangling.h> | 
|  | #include <__ranges/enable_borrowed_range.h> | 
|  | #include <__ranges/size.h> | 
|  | #include <__ranges/view_interface.h> | 
|  | #include <concepts> | 
|  | #include <type_traits> | 
|  |  | 
|  | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | 
|  | #pragma GCC system_header | 
|  | #endif | 
|  |  | 
|  | _LIBCPP_PUSH_MACROS | 
|  | #include <__undef_macros> | 
|  |  | 
|  | _LIBCPP_BEGIN_NAMESPACE_STD | 
|  |  | 
|  | #if !defined(_LIBCPP_HAS_NO_RANGES) | 
|  |  | 
|  | // clang-format off | 
|  | namespace ranges { | 
|  | template<class _From, class _To> | 
|  | concept __convertible_to_non_slicing = | 
|  | convertible_to<_From, _To> && | 
|  | // If they're both pointers, they must have the same element type. | 
|  | !(is_pointer_v<decay_t<_From>> && | 
|  | is_pointer_v<decay_t<_To>> && | 
|  | __different_from<remove_pointer_t<decay_t<_From>>, remove_pointer_t<decay_t<_To>>>); | 
|  |  | 
|  | template<class _Tp> | 
|  | concept __pair_like = | 
|  | !is_reference_v<_Tp> && requires(_Tp __t) { | 
|  | typename tuple_size<_Tp>::type; // Ensures `tuple_size<T>` is complete. | 
|  | requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>; | 
|  | typename tuple_element_t<0, remove_const_t<_Tp>>; | 
|  | typename tuple_element_t<1, remove_const_t<_Tp>>; | 
|  | { _VSTD::get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>; | 
|  | { _VSTD::get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>; | 
|  | }; | 
|  |  | 
|  | template<class _Pair, class _Iter, class _Sent> | 
|  | concept __pair_like_convertible_from = | 
|  | !range<_Pair> && __pair_like<_Pair> && | 
|  | constructible_from<_Pair, _Iter, _Sent> && | 
|  | __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && | 
|  | convertible_to<_Sent, tuple_element_t<1, _Pair>>; | 
|  |  | 
|  | enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized }; | 
|  |  | 
|  | template<class _Iter, class _Sent, bool> | 
|  | struct __subrange_base { | 
|  | static constexpr bool __store_size = false; | 
|  | _Iter __begin_ = _Iter(); | 
|  | _Sent __end_ = _Sent(); | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr __subrange_base() = default; | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr __subrange_base(_Iter __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> = 0) | 
|  | : __begin_(_VSTD::move(__iter)), __end_(__sent) { } | 
|  | }; | 
|  |  | 
|  | template<class _Iter, class _Sent> | 
|  | struct __subrange_base<_Iter, _Sent, true> { | 
|  | static constexpr bool __store_size = true; | 
|  | _Iter __begin_ = _Iter(); | 
|  | _Sent __end_ = _Sent(); | 
|  | make_unsigned_t<iter_difference_t<_Iter>> __size_ = 0; | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr __subrange_base() = default; | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr __subrange_base(_Iter __iter, _Sent __sent, decltype(__size_) __size) | 
|  | : __begin_(_VSTD::move(__iter)), __end_(__sent), __size_(__size) { } | 
|  | }; | 
|  |  | 
|  | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, | 
|  | subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> | 
|  | ? subrange_kind::sized | 
|  | : subrange_kind::unsized> | 
|  | requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) | 
|  | struct _LIBCPP_TEMPLATE_VIS subrange | 
|  | : public view_interface<subrange<_Iter, _Sent, _Kind>>, | 
|  | private __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>> { | 
|  |  | 
|  | using _Base = __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>>; | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | subrange() requires default_initializable<_Iter> = default; | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent) | 
|  | requires (!_Base::__store_size) | 
|  | : _Base(_VSTD::move(__iter), __sent) {} | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, | 
|  | make_unsigned_t<iter_difference_t<_Iter>> __n) | 
|  | requires (_Kind == subrange_kind::sized) | 
|  | : _Base(_VSTD::move(__iter), __sent, __n) { } | 
|  |  | 
|  | template<__different_from<subrange> _Range> | 
|  | requires borrowed_range<_Range> && | 
|  | __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | 
|  | convertible_to<sentinel_t<_Range>, _Sent> | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange(_Range&& __range) | 
|  | requires (!_Base::__store_size) | 
|  | : subrange(ranges::begin(__range), ranges::end(__range)) { } | 
|  |  | 
|  | template<__different_from<subrange> _Range> | 
|  | requires borrowed_range<_Range> && | 
|  | __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | 
|  | convertible_to<sentinel_t<_Range>, _Sent> | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange(_Range&& __range) | 
|  | requires _Base::__store_size && sized_range<_Range> | 
|  | : subrange(__range, ranges::size(__range)) { } | 
|  |  | 
|  |  | 
|  | template<borrowed_range _Range> | 
|  | requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && | 
|  | convertible_to<sentinel_t<_Range>, _Sent> | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n) | 
|  | requires (_Kind == subrange_kind::sized) | 
|  | : subrange(ranges::begin(__range), ranges::end(__range), __n) { } | 
|  |  | 
|  | template<__different_from<subrange> _Pair> | 
|  | requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&> | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr operator _Pair() const { return _Pair(this->__begin_, this->__end_); } | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr _Iter begin() const requires copyable<_Iter> { | 
|  | return this->__begin_; | 
|  | } | 
|  |  | 
|  | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) { | 
|  | return _VSTD::move(this->__begin_); | 
|  | } | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr _Sent end() const { return this->__end_; } | 
|  |  | 
|  | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return this->__begin_ == this->__end_; } | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const | 
|  | requires (_Kind == subrange_kind::sized) | 
|  | { | 
|  | if constexpr (_Base::__store_size) | 
|  | return this->__size_; | 
|  | else | 
|  | return __to_unsigned_like(this->__end_ - this->__begin_); | 
|  | } | 
|  |  | 
|  | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const& | 
|  | requires forward_iterator<_Iter> { | 
|  | auto __tmp = *this; | 
|  | __tmp.advance(__n); | 
|  | return __tmp; | 
|  | } | 
|  |  | 
|  | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && { | 
|  | advance(__n); | 
|  | return _VSTD::move(*this); | 
|  | } | 
|  |  | 
|  | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const | 
|  | requires bidirectional_iterator<_Iter> { | 
|  | auto __tmp = *this; | 
|  | __tmp.advance(-__n); | 
|  | return __tmp; | 
|  | } | 
|  |  | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr subrange& advance(iter_difference_t<_Iter> __n) { | 
|  | if constexpr (bidirectional_iterator<_Iter>) { | 
|  | if (__n < 0) { | 
|  | ranges::advance(this->__begin_, __n); | 
|  | if constexpr (_Base::__store_size) | 
|  | this->__size_ += _VSTD::__to_unsigned_like(-__n); | 
|  | return *this; | 
|  | } | 
|  | } | 
|  |  | 
|  | auto __d = __n - ranges::advance(this->__begin_, __n, this->__end_); | 
|  | if constexpr (_Base::__store_size) | 
|  | this->__size_ -= _VSTD::__to_unsigned_like(__d); | 
|  | return *this; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> | 
|  | subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>; | 
|  |  | 
|  | template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> | 
|  | subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) | 
|  | -> subrange<_Iter, _Sent, subrange_kind::sized>; | 
|  |  | 
|  | template<borrowed_range _Range> | 
|  | subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>, | 
|  | (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>) | 
|  | ? subrange_kind::sized : subrange_kind::unsized>; | 
|  |  | 
|  | template<borrowed_range _Range> | 
|  | subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>) | 
|  | -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>; | 
|  |  | 
|  | template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> | 
|  | requires (_Index < 2) | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) { | 
|  | if constexpr (_Index == 0) | 
|  | return __subrange.begin(); | 
|  | else | 
|  | return __subrange.end(); | 
|  | } | 
|  |  | 
|  | template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> | 
|  | requires (_Index < 2) | 
|  | _LIBCPP_HIDE_FROM_ABI | 
|  | constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) { | 
|  | if constexpr (_Index == 0) | 
|  | return __subrange.begin(); | 
|  | else | 
|  | return __subrange.end(); | 
|  | } | 
|  |  | 
|  | template<class _Ip, class _Sp, subrange_kind _Kp> | 
|  | inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true; | 
|  |  | 
|  | template<range _Rp> | 
|  | using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp> >, dangling>; | 
|  | } // namespace ranges | 
|  |  | 
|  | using ranges::get; | 
|  |  | 
|  | // clang-format off | 
|  |  | 
|  | #endif // !defined(_LIBCPP_HAS_NO_RANGES) | 
|  |  | 
|  | _LIBCPP_END_NAMESPACE_STD | 
|  |  | 
|  | _LIBCPP_POP_MACROS | 
|  |  | 
|  | #endif // _LIBCPP___RANGES_SUBRANGE_H |