File indexing completed on 2026-05-03 08:14:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___RANGES_TAKE_VIEW_H
0011 #define _LIBCPP___RANGES_TAKE_VIEW_H
0012
0013 #include <__algorithm/min.h>
0014 #include <__algorithm/ranges_min.h>
0015 #include <__assert>
0016 #include <__concepts/constructible.h>
0017 #include <__concepts/convertible_to.h>
0018 #include <__config>
0019 #include <__functional/bind_back.h>
0020 #include <__fwd/span.h>
0021 #include <__fwd/string_view.h>
0022 #include <__iterator/concepts.h>
0023 #include <__iterator/counted_iterator.h>
0024 #include <__iterator/default_sentinel.h>
0025 #include <__iterator/distance.h>
0026 #include <__iterator/iterator_traits.h>
0027 #include <__ranges/access.h>
0028 #include <__ranges/all.h>
0029 #include <__ranges/concepts.h>
0030 #include <__ranges/empty_view.h>
0031 #include <__ranges/enable_borrowed_range.h>
0032 #include <__ranges/iota_view.h>
0033 #include <__ranges/range_adaptor.h>
0034 #include <__ranges/repeat_view.h>
0035 #include <__ranges/size.h>
0036 #include <__ranges/subrange.h>
0037 #include <__ranges/view_interface.h>
0038 #include <__type_traits/decay.h>
0039 #include <__type_traits/is_nothrow_constructible.h>
0040 #include <__type_traits/maybe_const.h>
0041 #include <__type_traits/remove_cvref.h>
0042 #include <__utility/auto_cast.h>
0043 #include <__utility/forward.h>
0044 #include <__utility/move.h>
0045
0046 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0047 # pragma GCC system_header
0048 #endif
0049
0050 _LIBCPP_PUSH_MACROS
0051 #include <__undef_macros>
0052
0053 _LIBCPP_BEGIN_NAMESPACE_STD
0054
0055 #if _LIBCPP_STD_VER >= 20
0056
0057 namespace ranges {
0058
0059 template <view _View>
0060 class take_view : public view_interface<take_view<_View>> {
0061 _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
0062 range_difference_t<_View> __count_ = 0;
0063
0064 template <bool>
0065 class __sentinel;
0066
0067 public:
0068 _LIBCPP_HIDE_FROM_ABI take_view()
0069 requires default_initializable<_View>
0070 = default;
0071
0072 _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23
0073 take_view(_View __base, range_difference_t<_View> __count)
0074 : __base_(std::move(__base)), __count_(__count) {
0075 _LIBCPP_ASSERT_UNCATEGORIZED(__count >= 0, "count has to be greater than or equal to zero");
0076 }
0077
0078 _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
0079 requires copy_constructible<_View>
0080 {
0081 return __base_;
0082 }
0083
0084 _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
0085
0086 _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
0087 requires(!__simple_view<_View>)
0088 {
0089 if constexpr (sized_range<_View>) {
0090 if constexpr (random_access_range<_View>) {
0091 return ranges::begin(__base_);
0092 } else {
0093 using _DifferenceT = range_difference_t<_View>;
0094 auto __size = size();
0095 return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size));
0096 }
0097 } else {
0098 return counted_iterator(ranges::begin(__base_), __count_);
0099 }
0100 }
0101
0102 _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
0103 requires range<const _View>
0104 {
0105 if constexpr (sized_range<const _View>) {
0106 if constexpr (random_access_range<const _View>) {
0107 return ranges::begin(__base_);
0108 } else {
0109 using _DifferenceT = range_difference_t<const _View>;
0110 auto __size = size();
0111 return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size));
0112 }
0113 } else {
0114 return counted_iterator(ranges::begin(__base_), __count_);
0115 }
0116 }
0117
0118 _LIBCPP_HIDE_FROM_ABI constexpr auto end()
0119 requires(!__simple_view<_View>)
0120 {
0121 if constexpr (sized_range<_View>) {
0122 if constexpr (random_access_range<_View>) {
0123 return ranges::begin(__base_) + size();
0124 } else {
0125 return default_sentinel;
0126 }
0127 } else {
0128 return __sentinel<false>{ranges::end(__base_)};
0129 }
0130 }
0131
0132 _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
0133 requires range<const _View>
0134 {
0135 if constexpr (sized_range<const _View>) {
0136 if constexpr (random_access_range<const _View>) {
0137 return ranges::begin(__base_) + size();
0138 } else {
0139 return default_sentinel;
0140 }
0141 } else {
0142 return __sentinel<true>{ranges::end(__base_)};
0143 }
0144 }
0145
0146 _LIBCPP_HIDE_FROM_ABI constexpr auto size()
0147 requires sized_range<_View>
0148 {
0149 auto __n = ranges::size(__base_);
0150 return ranges::min(__n, static_cast<decltype(__n)>(__count_));
0151 }
0152
0153 _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
0154 requires sized_range<const _View>
0155 {
0156 auto __n = ranges::size(__base_);
0157 return ranges::min(__n, static_cast<decltype(__n)>(__count_));
0158 }
0159 };
0160
0161 template <view _View>
0162 template <bool _Const>
0163 class take_view<_View>::__sentinel {
0164 using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
0165 template <bool _OtherConst>
0166 using _Iter _LIBCPP_NODEBUG = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>;
0167 _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
0168
0169 template <bool>
0170 friend class take_view<_View>::__sentinel;
0171
0172 public:
0173 _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
0174
0175 _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
0176
0177 _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
0178 requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
0179 : __end_(std::move(__s.__end_)) {}
0180
0181 _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; }
0182
0183 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) {
0184 return __lhs.count() == 0 || __lhs.base() == __rhs.__end_;
0185 }
0186
0187 template <bool _OtherConst = !_Const>
0188 requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
0189 _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const _Iter<_OtherConst>& __lhs, const __sentinel& __rhs) {
0190 return __lhs.count() == 0 || __lhs.base() == __rhs.__end_;
0191 }
0192 };
0193
0194 template <class _Range>
0195 take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>;
0196
0197 template <class _Tp>
0198 inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>;
0199
0200 namespace views {
0201 namespace __take {
0202
0203 template <class _Tp>
0204 inline constexpr bool __is_empty_view = false;
0205
0206 template <class _Tp>
0207 inline constexpr bool __is_empty_view<empty_view<_Tp>> = true;
0208
0209 template <class _Tp>
0210 inline constexpr bool __is_passthrough_specialization = false;
0211
0212 template <class _Tp, size_t _Extent>
0213 inline constexpr bool __is_passthrough_specialization<span<_Tp, _Extent>> = true;
0214
0215 template <class _CharT, class _Traits>
0216 inline constexpr bool __is_passthrough_specialization<basic_string_view<_CharT, _Traits>> = true;
0217
0218 template <class _Iter, class _Sent, subrange_kind _Kind>
0219 inline constexpr bool __is_passthrough_specialization<subrange<_Iter, _Sent, _Kind>> = true;
0220
0221 template <class _Tp>
0222 inline constexpr bool __is_iota_specialization = false;
0223
0224 template <class _Np, class _Bound>
0225 inline constexpr bool __is_iota_specialization<iota_view<_Np, _Bound>> = true;
0226
0227 template <class _Tp>
0228 struct __passthrough_type;
0229
0230 template <class _Tp, size_t _Extent>
0231 struct __passthrough_type<span<_Tp, _Extent>> {
0232 using type = span<_Tp>;
0233 };
0234
0235 template <class _CharT, class _Traits>
0236 struct __passthrough_type<basic_string_view<_CharT, _Traits>> {
0237 using type = basic_string_view<_CharT, _Traits>;
0238 };
0239
0240 template <class _Iter, class _Sent, subrange_kind _Kind>
0241 requires requires { typename subrange<_Iter>; }
0242 struct __passthrough_type<subrange<_Iter, _Sent, _Kind>> {
0243 using type = subrange<_Iter>;
0244 };
0245
0246 template <class _Tp>
0247 using __passthrough_type_t _LIBCPP_NODEBUG = typename __passthrough_type<_Tp>::type;
0248
0249 struct __fn {
0250
0251 template <class _Range, convertible_to<range_difference_t<_Range>> _Np>
0252 requires __is_empty_view<remove_cvref_t<_Range>>
0253 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&&) const
0254 noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range))))
0255 -> decltype(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) {
0256 return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range));
0257 }
0258
0259
0260 template <class _Range,
0261 convertible_to<range_difference_t<_Range>> _Np,
0262 class _RawRange = remove_cvref_t<_Range>,
0263 class _Dist = range_difference_t<_Range>>
0264 requires(!__is_empty_view<_RawRange> && random_access_range<_RawRange> && sized_range<_RawRange> &&
0265 __is_passthrough_specialization<_RawRange>)
0266 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto
0267 operator()(_Range&& __rng, _Np&& __n) const noexcept(noexcept(__passthrough_type_t<_RawRange>(
0268 ranges::begin(__rng), ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))))
0269 -> decltype(__passthrough_type_t<_RawRange>(
0270
0271 ranges::begin(__rng),
0272 ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))) {
0273 return __passthrough_type_t<_RawRange>(
0274 ranges::begin(__rng), ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)));
0275 }
0276
0277
0278
0279 template <class _Range,
0280 convertible_to<range_difference_t<_Range>> _Np,
0281 class _RawRange = remove_cvref_t<_Range>,
0282 class _Dist = range_difference_t<_Range>>
0283 requires (!__is_empty_view<_RawRange> &&
0284 random_access_range<_RawRange> &&
0285 sized_range<_RawRange> &&
0286 __is_iota_specialization<_RawRange>)
0287 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
0288 constexpr auto operator()(_Range&& __rng, _Np&& __n) const
0289 noexcept(noexcept(ranges::iota_view(
0290 *ranges::begin(__rng),
0291 *(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
0292 )))
0293 -> decltype( ranges::iota_view(
0294
0295 *ranges::begin(__rng),
0296 *(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
0297 ))
0298 { return ranges::iota_view(
0299 *ranges::begin(__rng),
0300 *(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
0301 ); }
0302
0303 #if _LIBCPP_STD_VER >= 23
0304
0305 template <class _Range,
0306 convertible_to<range_difference_t<_Range>> _Np,
0307 class _RawRange = remove_cvref_t<_Range>,
0308 class _Dist = range_difference_t<_Range>>
0309 requires(__is_repeat_specialization<_RawRange> && sized_range<_RawRange>)
0310 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const
0311 noexcept(noexcept(views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))))
0312 -> decltype( views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))
0313 { return views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); }
0314
0315
0316 template <class _Range,
0317 convertible_to<range_difference_t<_Range>> _Np,
0318 class _RawRange = remove_cvref_t<_Range>,
0319 class _Dist = range_difference_t<_Range>>
0320 requires(__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>)
0321 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const
0322 noexcept(noexcept(views::repeat(*__range.__value_, static_cast<_Dist>(__n))))
0323 -> decltype( views::repeat(*__range.__value_, static_cast<_Dist>(__n)))
0324 { return views::repeat(*__range.__value_, static_cast<_Dist>(__n)); }
0325 #endif
0326
0327
0328
0329 template <class _Range, convertible_to<range_difference_t<_Range>> _Np, class _RawRange = remove_cvref_t<_Range>>
0330
0331
0332 requires(!(__is_empty_view<_RawRange> ||
0333 # if _LIBCPP_STD_VER >= 23
0334 __is_repeat_specialization<_RawRange> ||
0335 # endif
0336 (__is_iota_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) ||
0337 (__is_passthrough_specialization<_RawRange> && sized_range<_RawRange> &&
0338 random_access_range<_RawRange>)))
0339 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const
0340 noexcept(noexcept(take_view(std::forward<_Range>(__range), std::forward<_Np>(__n))))
0341 -> decltype(take_view(std::forward<_Range>(__range), std::forward<_Np>(__n))) {
0342 return take_view(std::forward<_Range>(__range), std::forward<_Np>(__n));
0343 }
0344
0345 template <class _Np>
0346 requires constructible_from<decay_t<_Np>, _Np>
0347 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Np&& __n) const
0348 noexcept(is_nothrow_constructible_v<decay_t<_Np>, _Np>) {
0349 return __pipeable(std::__bind_back(*this, std::forward<_Np>(__n)));
0350 }
0351 };
0352
0353 }
0354
0355 inline namespace __cpo {
0356 inline constexpr auto take = __take::__fn{};
0357 }
0358 }
0359
0360 }
0361
0362 #endif
0363
0364 _LIBCPP_END_NAMESPACE_STD
0365
0366 _LIBCPP_POP_MACROS
0367
0368 #endif