Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:14:03

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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   // [range.take.overview]: the `empty_view` case.
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   // [range.take.overview]: the `span | basic_string_view | subrange` case.
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           // Note: deliberately not forwarding `__rng` to guard against double moves.
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   // [range.take.overview]: the `iota_view` case.
0278   // clang-format off
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                               // Note: deliberately not forwarding `__rng` to guard against double moves.
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   // [range.take.overview]: the `repeat_view` "_RawRange models sized_range" case.
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   // [range.take.overview]: the `repeat_view` "otherwise" case.
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   // clang-format on
0327 
0328   // [range.take.overview]: the "otherwise" case.
0329   template <class _Range, convertible_to<range_difference_t<_Range>> _Np, class _RawRange = remove_cvref_t<_Range>>
0330   // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other
0331   // overloads.
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 } // namespace __take
0354 
0355 inline namespace __cpo {
0356 inline constexpr auto take = __take::__fn{};
0357 } // namespace __cpo
0358 } // namespace views
0359 
0360 } // namespace ranges
0361 
0362 #endif // _LIBCPP_STD_VER >= 20
0363 
0364 _LIBCPP_END_NAMESPACE_STD
0365 
0366 _LIBCPP_POP_MACROS
0367 
0368 #endif // _LIBCPP___RANGES_TAKE_VIEW_H