1*4bdff4beSrobert // -*- C++ -*- 2*4bdff4beSrobert //===----------------------------------------------------------------------===// 3*4bdff4beSrobert // 4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information. 6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4bdff4beSrobert // 8*4bdff4beSrobert //===----------------------------------------------------------------------===// 9*4bdff4beSrobert 10*4bdff4beSrobert #ifndef _LIBCPP___RANGES_TAKE_VIEW_H 11*4bdff4beSrobert #define _LIBCPP___RANGES_TAKE_VIEW_H 12*4bdff4beSrobert 13*4bdff4beSrobert #include <__algorithm/min.h> 14*4bdff4beSrobert #include <__algorithm/ranges_min.h> 15*4bdff4beSrobert #include <__assert> 16*4bdff4beSrobert #include <__concepts/constructible.h> 17*4bdff4beSrobert #include <__concepts/convertible_to.h> 18*4bdff4beSrobert #include <__config> 19*4bdff4beSrobert #include <__functional/bind_back.h> 20*4bdff4beSrobert #include <__fwd/span.h> 21*4bdff4beSrobert #include <__fwd/string_view.h> 22*4bdff4beSrobert #include <__iterator/concepts.h> 23*4bdff4beSrobert #include <__iterator/counted_iterator.h> 24*4bdff4beSrobert #include <__iterator/default_sentinel.h> 25*4bdff4beSrobert #include <__iterator/distance.h> 26*4bdff4beSrobert #include <__iterator/iterator_traits.h> 27*4bdff4beSrobert #include <__ranges/access.h> 28*4bdff4beSrobert #include <__ranges/all.h> 29*4bdff4beSrobert #include <__ranges/concepts.h> 30*4bdff4beSrobert #include <__ranges/empty_view.h> 31*4bdff4beSrobert #include <__ranges/enable_borrowed_range.h> 32*4bdff4beSrobert #include <__ranges/iota_view.h> 33*4bdff4beSrobert #include <__ranges/range_adaptor.h> 34*4bdff4beSrobert #include <__ranges/size.h> 35*4bdff4beSrobert #include <__ranges/subrange.h> 36*4bdff4beSrobert #include <__ranges/view_interface.h> 37*4bdff4beSrobert #include <__type_traits/maybe_const.h> 38*4bdff4beSrobert #include <__utility/auto_cast.h> 39*4bdff4beSrobert #include <__utility/forward.h> 40*4bdff4beSrobert #include <__utility/move.h> 41*4bdff4beSrobert #include <type_traits> 42*4bdff4beSrobert 43*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 44*4bdff4beSrobert # pragma GCC system_header 45*4bdff4beSrobert #endif 46*4bdff4beSrobert 47*4bdff4beSrobert _LIBCPP_PUSH_MACROS 48*4bdff4beSrobert #include <__undef_macros> 49*4bdff4beSrobert 50*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD 51*4bdff4beSrobert 52*4bdff4beSrobert #if _LIBCPP_STD_VER > 17 53*4bdff4beSrobert 54*4bdff4beSrobert namespace ranges { 55*4bdff4beSrobert 56*4bdff4beSrobert template<view _View> 57*4bdff4beSrobert class take_view : public view_interface<take_view<_View>> { 58*4bdff4beSrobert _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 59*4bdff4beSrobert range_difference_t<_View> __count_ = 0; 60*4bdff4beSrobert 61*4bdff4beSrobert template<bool> class __sentinel; 62*4bdff4beSrobert 63*4bdff4beSrobert public: 64*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 65*4bdff4beSrobert take_view() requires default_initializable<_View> = default; 66*4bdff4beSrobert take_view(_View __base,range_difference_t<_View> __count)67*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count) 68*4bdff4beSrobert : __base_(std::move(__base)), __count_(__count) { 69*4bdff4beSrobert _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero"); 70*4bdff4beSrobert } 71*4bdff4beSrobert 72*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI base()73*4bdff4beSrobert constexpr _View base() const& requires copy_constructible<_View> { return __base_; } 74*4bdff4beSrobert 75*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI base()76*4bdff4beSrobert constexpr _View base() && { return std::move(__base_); } 77*4bdff4beSrobert 78*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI begin()79*4bdff4beSrobert constexpr auto begin() requires (!__simple_view<_View>) { 80*4bdff4beSrobert if constexpr (sized_range<_View>) { 81*4bdff4beSrobert if constexpr (random_access_range<_View>) { 82*4bdff4beSrobert return ranges::begin(__base_); 83*4bdff4beSrobert } else { 84*4bdff4beSrobert using _DifferenceT = range_difference_t<_View>; 85*4bdff4beSrobert auto __size = size(); 86*4bdff4beSrobert return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); 87*4bdff4beSrobert } 88*4bdff4beSrobert } else { 89*4bdff4beSrobert return counted_iterator(ranges::begin(__base_), __count_); 90*4bdff4beSrobert } 91*4bdff4beSrobert } 92*4bdff4beSrobert 93*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI begin()94*4bdff4beSrobert constexpr auto begin() const requires range<const _View> { 95*4bdff4beSrobert if constexpr (sized_range<const _View>) { 96*4bdff4beSrobert if constexpr (random_access_range<const _View>) { 97*4bdff4beSrobert return ranges::begin(__base_); 98*4bdff4beSrobert } else { 99*4bdff4beSrobert using _DifferenceT = range_difference_t<const _View>; 100*4bdff4beSrobert auto __size = size(); 101*4bdff4beSrobert return counted_iterator(ranges::begin(__base_), static_cast<_DifferenceT>(__size)); 102*4bdff4beSrobert } 103*4bdff4beSrobert } else { 104*4bdff4beSrobert return counted_iterator(ranges::begin(__base_), __count_); 105*4bdff4beSrobert } 106*4bdff4beSrobert } 107*4bdff4beSrobert 108*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI end()109*4bdff4beSrobert constexpr auto end() requires (!__simple_view<_View>) { 110*4bdff4beSrobert if constexpr (sized_range<_View>) { 111*4bdff4beSrobert if constexpr (random_access_range<_View>) { 112*4bdff4beSrobert return ranges::begin(__base_) + size(); 113*4bdff4beSrobert } else { 114*4bdff4beSrobert return default_sentinel; 115*4bdff4beSrobert } 116*4bdff4beSrobert } else { 117*4bdff4beSrobert return __sentinel<false>{ranges::end(__base_)}; 118*4bdff4beSrobert } 119*4bdff4beSrobert } 120*4bdff4beSrobert 121*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI end()122*4bdff4beSrobert constexpr auto end() const requires range<const _View> { 123*4bdff4beSrobert if constexpr (sized_range<const _View>) { 124*4bdff4beSrobert if constexpr (random_access_range<const _View>) { 125*4bdff4beSrobert return ranges::begin(__base_) + size(); 126*4bdff4beSrobert } else { 127*4bdff4beSrobert return default_sentinel; 128*4bdff4beSrobert } 129*4bdff4beSrobert } else { 130*4bdff4beSrobert return __sentinel<true>{ranges::end(__base_)}; 131*4bdff4beSrobert } 132*4bdff4beSrobert } 133*4bdff4beSrobert 134*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI size()135*4bdff4beSrobert constexpr auto size() requires sized_range<_View> { 136*4bdff4beSrobert auto __n = ranges::size(__base_); 137*4bdff4beSrobert return ranges::min(__n, static_cast<decltype(__n)>(__count_)); 138*4bdff4beSrobert } 139*4bdff4beSrobert 140*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI size()141*4bdff4beSrobert constexpr auto size() const requires sized_range<const _View> { 142*4bdff4beSrobert auto __n = ranges::size(__base_); 143*4bdff4beSrobert return ranges::min(__n, static_cast<decltype(__n)>(__count_)); 144*4bdff4beSrobert } 145*4bdff4beSrobert }; 146*4bdff4beSrobert 147*4bdff4beSrobert template<view _View> 148*4bdff4beSrobert template<bool _Const> 149*4bdff4beSrobert class take_view<_View>::__sentinel { 150*4bdff4beSrobert using _Base = __maybe_const<_Const, _View>; 151*4bdff4beSrobert template<bool _OtherConst> 152*4bdff4beSrobert using _Iter = counted_iterator<iterator_t<__maybe_const<_OtherConst, _View>>>; 153*4bdff4beSrobert _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); 154*4bdff4beSrobert 155*4bdff4beSrobert template<bool> 156*4bdff4beSrobert friend class take_view<_View>::__sentinel; 157*4bdff4beSrobert 158*4bdff4beSrobert public: 159*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 160*4bdff4beSrobert __sentinel() = default; 161*4bdff4beSrobert 162*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI __sentinel(sentinel_t<_Base> __end)163*4bdff4beSrobert constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} 164*4bdff4beSrobert 165*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI __sentinel(__sentinel<!_Const> __s)166*4bdff4beSrobert constexpr __sentinel(__sentinel<!_Const> __s) 167*4bdff4beSrobert requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> 168*4bdff4beSrobert : __end_(std::move(__s.__end_)) {} 169*4bdff4beSrobert 170*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI base()171*4bdff4beSrobert constexpr sentinel_t<_Base> base() const { return __end_; } 172*4bdff4beSrobert 173*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 174*4bdff4beSrobert friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { 175*4bdff4beSrobert return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; 176*4bdff4beSrobert } 177*4bdff4beSrobert 178*4bdff4beSrobert template<bool _OtherConst = !_Const> 179*4bdff4beSrobert requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 180*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI 181*4bdff4beSrobert friend constexpr bool operator==(const _Iter<_Const>& __lhs, const __sentinel& __rhs) { 182*4bdff4beSrobert return __lhs.count() == 0 || __lhs.base() == __rhs.__end_; 183*4bdff4beSrobert } 184*4bdff4beSrobert }; 185*4bdff4beSrobert 186*4bdff4beSrobert template<class _Range> 187*4bdff4beSrobert take_view(_Range&&, range_difference_t<_Range>) -> take_view<views::all_t<_Range>>; 188*4bdff4beSrobert 189*4bdff4beSrobert template<class _Tp> 190*4bdff4beSrobert inline constexpr bool enable_borrowed_range<take_view<_Tp>> = enable_borrowed_range<_Tp>; 191*4bdff4beSrobert 192*4bdff4beSrobert namespace views { 193*4bdff4beSrobert namespace __take { 194*4bdff4beSrobert 195*4bdff4beSrobert template <class _Tp> 196*4bdff4beSrobert inline constexpr bool __is_empty_view = false; 197*4bdff4beSrobert 198*4bdff4beSrobert template <class _Tp> 199*4bdff4beSrobert inline constexpr bool __is_empty_view<empty_view<_Tp>> = true; 200*4bdff4beSrobert 201*4bdff4beSrobert template <class _Tp> 202*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization = false; 203*4bdff4beSrobert 204*4bdff4beSrobert template <class _Tp, size_t _Extent> 205*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<span<_Tp, _Extent>> = true; 206*4bdff4beSrobert 207*4bdff4beSrobert template <class _CharT, class _Traits> 208*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<basic_string_view<_CharT, _Traits>> = true; 209*4bdff4beSrobert 210*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind> 211*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<subrange<_Iter, _Sent, _Kind>> = true; 212*4bdff4beSrobert 213*4bdff4beSrobert template <class _Tp> 214*4bdff4beSrobert inline constexpr bool __is_iota_specialization = false; 215*4bdff4beSrobert 216*4bdff4beSrobert template <class _Np, class _Bound> 217*4bdff4beSrobert inline constexpr bool __is_iota_specialization<iota_view<_Np, _Bound>> = true; 218*4bdff4beSrobert 219*4bdff4beSrobert template <class _Tp> 220*4bdff4beSrobert struct __passthrough_type; 221*4bdff4beSrobert 222*4bdff4beSrobert template <class _Tp, size_t _Extent> 223*4bdff4beSrobert struct __passthrough_type<span<_Tp, _Extent>> { 224*4bdff4beSrobert using type = span<_Tp>; 225*4bdff4beSrobert }; 226*4bdff4beSrobert 227*4bdff4beSrobert template <class _CharT, class _Traits> 228*4bdff4beSrobert struct __passthrough_type<basic_string_view<_CharT, _Traits>> { 229*4bdff4beSrobert using type = basic_string_view<_CharT, _Traits>; 230*4bdff4beSrobert }; 231*4bdff4beSrobert 232*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind> 233*4bdff4beSrobert requires requires{typename subrange<_Iter>;} 234*4bdff4beSrobert struct __passthrough_type<subrange<_Iter, _Sent, _Kind>> { 235*4bdff4beSrobert using type = subrange<_Iter>; 236*4bdff4beSrobert }; 237*4bdff4beSrobert 238*4bdff4beSrobert template <class _Tp> 239*4bdff4beSrobert using __passthrough_type_t = typename __passthrough_type<_Tp>::type; 240*4bdff4beSrobert 241*4bdff4beSrobert struct __fn { 242*4bdff4beSrobert // [range.take.overview]: the `empty_view` case. 243*4bdff4beSrobert template <class _Range, convertible_to<range_difference_t<_Range>> _Np> 244*4bdff4beSrobert requires __is_empty_view<remove_cvref_t<_Range>> 245*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 246*4bdff4beSrobert constexpr auto operator()(_Range&& __range, _Np&&) const 247*4bdff4beSrobert noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) 248*4bdff4beSrobert -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) 249*4bdff4beSrobert { return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); } 250*4bdff4beSrobert 251*4bdff4beSrobert // [range.take.overview]: the `span | basic_string_view | subrange` case. 252*4bdff4beSrobert template <class _Range, 253*4bdff4beSrobert convertible_to<range_difference_t<_Range>> _Np, 254*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>, 255*4bdff4beSrobert class _Dist = range_difference_t<_Range>> 256*4bdff4beSrobert requires (!__is_empty_view<_RawRange> && 257*4bdff4beSrobert random_access_range<_RawRange> && 258*4bdff4beSrobert sized_range<_RawRange> && 259*4bdff4beSrobert __is_passthrough_specialization<_RawRange>) 260*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 261*4bdff4beSrobert constexpr auto operator()(_Range&& __rng, _Np&& __n) const 262*4bdff4beSrobert noexcept(noexcept(__passthrough_type_t<_RawRange>( 263*4bdff4beSrobert ranges::begin(__rng), 264*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 265*4bdff4beSrobert ))) 266*4bdff4beSrobert -> decltype( __passthrough_type_t<_RawRange>( 267*4bdff4beSrobert // Note: deliberately not forwarding `__rng` to guard against double moves. 268*4bdff4beSrobert ranges::begin(__rng), 269*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 270*4bdff4beSrobert )) 271*4bdff4beSrobert { return __passthrough_type_t<_RawRange>( 272*4bdff4beSrobert ranges::begin(__rng), 273*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 274*4bdff4beSrobert ); } 275*4bdff4beSrobert 276*4bdff4beSrobert // [range.take.overview]: the `iota_view` case. 277*4bdff4beSrobert template <class _Range, 278*4bdff4beSrobert convertible_to<range_difference_t<_Range>> _Np, 279*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>, 280*4bdff4beSrobert class _Dist = range_difference_t<_Range>> 281*4bdff4beSrobert requires (!__is_empty_view<_RawRange> && 282*4bdff4beSrobert random_access_range<_RawRange> && 283*4bdff4beSrobert sized_range<_RawRange> && 284*4bdff4beSrobert __is_iota_specialization<_RawRange>) 285*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 286*4bdff4beSrobert constexpr auto operator()(_Range&& __rng, _Np&& __n) const 287*4bdff4beSrobert noexcept(noexcept(ranges::iota_view( 288*4bdff4beSrobert *ranges::begin(__rng), 289*4bdff4beSrobert *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 290*4bdff4beSrobert ))) 291*4bdff4beSrobert -> decltype( ranges::iota_view( 292*4bdff4beSrobert // Note: deliberately not forwarding `__rng` to guard against double moves. 293*4bdff4beSrobert *ranges::begin(__rng), 294*4bdff4beSrobert *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 295*4bdff4beSrobert )) 296*4bdff4beSrobert { return ranges::iota_view( 297*4bdff4beSrobert *ranges::begin(__rng), 298*4bdff4beSrobert *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) 299*4bdff4beSrobert ); } 300*4bdff4beSrobert 301*4bdff4beSrobert // [range.take.overview]: the "otherwise" case. 302*4bdff4beSrobert template <class _Range, convertible_to<range_difference_t<_Range>> _Np, 303*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>> 304*4bdff4beSrobert // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other 305*4bdff4beSrobert // overloads. 306*4bdff4beSrobert requires (!(__is_empty_view<_RawRange> || 307*4bdff4beSrobert (__is_iota_specialization<_RawRange> && 308*4bdff4beSrobert sized_range<_RawRange> && 309*4bdff4beSrobert random_access_range<_RawRange>) || 310*4bdff4beSrobert (__is_passthrough_specialization<_RawRange> && 311*4bdff4beSrobert sized_range<_RawRange> && 312*4bdff4beSrobert random_access_range<_RawRange>) 313*4bdff4beSrobert )) 314*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 315*4bdff4beSrobert constexpr auto operator()(_Range&& __range, _Np&& __n) const 316*4bdff4beSrobert noexcept(noexcept(take_view(std::forward<_Range>(__range), std::forward<_Np>(__n)))) 317*4bdff4beSrobert -> decltype( take_view(std::forward<_Range>(__range), std::forward<_Np>(__n))) 318*4bdff4beSrobert { return take_view(std::forward<_Range>(__range), std::forward<_Np>(__n)); } 319*4bdff4beSrobert 320*4bdff4beSrobert template <class _Np> 321*4bdff4beSrobert requires constructible_from<decay_t<_Np>, _Np> 322*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 323*4bdff4beSrobert constexpr auto operator()(_Np&& __n) const 324*4bdff4beSrobert noexcept(is_nothrow_constructible_v<decay_t<_Np>, _Np>) 325*4bdff4beSrobert { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Np>(__n))); } 326*4bdff4beSrobert }; 327*4bdff4beSrobert 328*4bdff4beSrobert } // namespace __take 329*4bdff4beSrobert 330*4bdff4beSrobert inline namespace __cpo { 331*4bdff4beSrobert inline constexpr auto take = __take::__fn{}; 332*4bdff4beSrobert } // namespace __cpo 333*4bdff4beSrobert } // namespace views 334*4bdff4beSrobert 335*4bdff4beSrobert } // namespace ranges 336*4bdff4beSrobert 337*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17 338*4bdff4beSrobert 339*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD 340*4bdff4beSrobert 341*4bdff4beSrobert _LIBCPP_POP_MACROS 342*4bdff4beSrobert 343*4bdff4beSrobert #endif // _LIBCPP___RANGES_TAKE_VIEW_H 344