1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef _LIBCPP___RANGES_TAKE_VIEW_H 10 #define _LIBCPP___RANGES_TAKE_VIEW_H 11 12 #include <__algorithm/min.h> 13 #include <__config> 14 #include <__iterator/concepts.h> 15 #include <__iterator/counted_iterator.h> 16 #include <__iterator/default_sentinel.h> 17 #include <__iterator/iterator_traits.h> 18 #include <__ranges/access.h> 19 #include <__ranges/all.h> 20 #include <__ranges/concepts.h> 21 #include <__ranges/enable_borrowed_range.h> 22 #include <__ranges/size.h> 23 #include <__ranges/view_interface.h> 24 #include <__utility/move.h> 25 #include <concepts> 26 #include <type_traits> 27 28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 29 #pragma GCC system_header 30 #endif 31 32 _LIBCPP_PUSH_MACROS 33 #include <__undef_macros> 34 35 _LIBCPP_BEGIN_NAMESPACE_STD 36 37 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 38 39 namespace ranges { 40 template<view _View> 41 class take_view : public view_interface<take_view<_View>> { 42 [[no_unique_address]] _View __base_ = _View(); 43 range_difference_t<_View> __count_ = 0; 44 45 template<bool> class __sentinel; 46 47 public: 48 _LIBCPP_HIDE_FROM_ABI 49 take_view() requires default_initializable<_View> = default; 50 51 _LIBCPP_HIDE_FROM_ABI 52 constexpr take_view(_View __base, range_difference_t<_View> __count) 53 : __base_(_VSTD::move(__base)), __count_(__count) {} 54 55 _LIBCPP_HIDE_FROM_ABI 56 constexpr _View base() const& requires copy_constructible<_View> { return __base_; } 57 58 _LIBCPP_HIDE_FROM_ABI 59 constexpr _View base() && { return _VSTD::move(__base_); } 60 61 _LIBCPP_HIDE_FROM_ABI 62 constexpr auto begin() requires (!__simple_view<_View>) { 63 if constexpr (sized_range<_View>) { 64 if constexpr (random_access_range<_View>) { 65 return ranges::begin(__base_); 66 } else { 67 using _DifferenceT = range_difference_t<_View>; 68 auto __size = size(); 69 return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); 70 } 71 } else { 72 return counted_iterator(ranges::begin(__base_), __count_); 73 } 74 } 75 76 _LIBCPP_HIDE_FROM_ABI 77 constexpr auto begin() const requires range<const _View> { 78 if constexpr (sized_range<const _View>) { 79 if constexpr (random_access_range<const _View>) { 80 return ranges::begin(__base_); 81 } else { 82 using _DifferenceT = range_difference_t<const _View>; 83 auto __size = size(); 84 return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); 85 } 86 } else { 87 return counted_iterator(ranges::begin(__base_), __count_); 88 } 89 } 90 91 _LIBCPP_HIDE_FROM_ABI 92 constexpr auto end() requires (!__simple_view<_View>) { 93 if constexpr (sized_range<_View>) { 94 if constexpr (random_access_range<_View>) { 95 return ranges::begin(__base_) + size(); 96 } else { 97 return default_sentinel; 98 } 99 } else { 100 return __sentinel<false>{ranges::end(__base_)}; 101 } 102 } 103 104 _LIBCPP_HIDE_FROM_ABI 105 constexpr auto end() const requires range<const _View> { 106 if constexpr (sized_range<const _View>) { 107 if constexpr (random_access_range<const _View>) { 108 return ranges::begin(__base_) + size(); 109 } else { 110 return default_sentinel; 111 } 112 } else { 113 return __sentinel<true>{ranges::end(__base_)}; 114 } 115 } 116 117 118 _LIBCPP_HIDE_FROM_ABI 119 constexpr auto size() requires sized_range<_View> { 120 auto __n = ranges::size(__base_); 121 // TODO: use ranges::min here. 122 return _VSTD::min(__n, static_cast<decltype(__n)>(__count_)); 123 } 124 125 _LIBCPP_HIDE_FROM_ABI 126 constexpr auto size() const requires sized_range<const _View> { 127 auto __n = ranges::size(__base_); 128 // TODO: use ranges::min here. 129 return _VSTD::min(__n, static_cast<decltype(__n)>(__count_)); 130 } 131 }; 132 133 template<view _View> 134 template<bool _Const> 135 class take_view<_View>::__sentinel { 136 using _Base = __maybe_const<_Const, _View>; 137 template<bool _OtherConst> 138 using _Iter = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>; 139 [[no_unique_address]] sentinel_t<_Base> __end_ = sentinel_t<_Base>(); 140 141 template<bool> 142 friend class take_view<_View>::__sentinel; 143 144 public: 145 _LIBCPP_HIDE_FROM_ABI 146 __sentinel() = default; 147 148 _LIBCPP_HIDE_FROM_ABI 149 constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(_VSTD::move(__end)) {} 150 151 _LIBCPP_HIDE_FROM_ABI 152 constexpr __sentinel(__sentinel<!_Const> __s) 153 requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> 154 : __end_(_VSTD::move(__s.__end_)) {} 155 156 _LIBCPP_HIDE_FROM_ABI 157 constexpr sentinel_t<_Base> base() const { return __end_; } 158 159 _LIBCPP_HIDE_FROM_ABI 160 friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { 161 return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; 162 } 163 164 template<bool _OtherConst = !_Const> 165 requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 166 _LIBCPP_HIDE_FROM_ABI 167 friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { 168 return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; 169 } 170 }; 171 172 template<class _Range> 173 take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>; 174 175 template<class _Tp> 176 inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>; 177 } // namespace ranges 178 179 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 180 181 _LIBCPP_END_NAMESPACE_STD 182 183 _LIBCPP_POP_MACROS 184 185 #endif // _LIBCPP___RANGES_TAKE_VIEW_H 186