176d0caaeSpatrick // -*- C++ -*- 276d0caaeSpatrick //===----------------------------------------------------------------------===// 376d0caaeSpatrick // 476d0caaeSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 576d0caaeSpatrick // See https://llvm.org/LICENSE.txt for license information. 676d0caaeSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 776d0caaeSpatrick // 876d0caaeSpatrick //===----------------------------------------------------------------------===// 9*4bdff4beSrobert 1076d0caaeSpatrick #ifndef _LIBCPP___RANGES_DROP_VIEW_H 1176d0caaeSpatrick #define _LIBCPP___RANGES_DROP_VIEW_H 1276d0caaeSpatrick 13*4bdff4beSrobert #include <__algorithm/min.h> 14*4bdff4beSrobert #include <__assert> 15*4bdff4beSrobert #include <__concepts/constructible.h> 16*4bdff4beSrobert #include <__concepts/convertible_to.h> 1776d0caaeSpatrick #include <__config> 18*4bdff4beSrobert #include <__functional/bind_back.h> 19*4bdff4beSrobert #include <__fwd/span.h> 20*4bdff4beSrobert #include <__fwd/string_view.h> 2176d0caaeSpatrick #include <__iterator/concepts.h> 22*4bdff4beSrobert #include <__iterator/distance.h> 2376d0caaeSpatrick #include <__iterator/iterator_traits.h> 2476d0caaeSpatrick #include <__iterator/next.h> 2576d0caaeSpatrick #include <__ranges/access.h> 2676d0caaeSpatrick #include <__ranges/all.h> 2776d0caaeSpatrick #include <__ranges/concepts.h> 28*4bdff4beSrobert #include <__ranges/empty_view.h> 2976d0caaeSpatrick #include <__ranges/enable_borrowed_range.h> 30*4bdff4beSrobert #include <__ranges/iota_view.h> 3176d0caaeSpatrick #include <__ranges/non_propagating_cache.h> 32*4bdff4beSrobert #include <__ranges/range_adaptor.h> 3376d0caaeSpatrick #include <__ranges/size.h> 34*4bdff4beSrobert #include <__ranges/subrange.h> 3576d0caaeSpatrick #include <__ranges/view_interface.h> 36*4bdff4beSrobert #include <__utility/auto_cast.h> 37*4bdff4beSrobert #include <__utility/forward.h> 3876d0caaeSpatrick #include <__utility/move.h> 3976d0caaeSpatrick #include <type_traits> 4076d0caaeSpatrick 4176d0caaeSpatrick #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 4276d0caaeSpatrick # pragma GCC system_header 4376d0caaeSpatrick #endif 4476d0caaeSpatrick 4576d0caaeSpatrick _LIBCPP_PUSH_MACROS 4676d0caaeSpatrick #include <__undef_macros> 4776d0caaeSpatrick 4876d0caaeSpatrick _LIBCPP_BEGIN_NAMESPACE_STD 4976d0caaeSpatrick 50*4bdff4beSrobert #if _LIBCPP_STD_VER > 17 5176d0caaeSpatrick 5276d0caaeSpatrick namespace ranges { 5376d0caaeSpatrick template<view _View> 5476d0caaeSpatrick class drop_view 5576d0caaeSpatrick : public view_interface<drop_view<_View>> 5676d0caaeSpatrick { 5776d0caaeSpatrick // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an 5876d0caaeSpatrick // amortized O(1) begin() method. If this is an input_range, then we cannot cache 5976d0caaeSpatrick // begin because begin is not equality preserving. 6076d0caaeSpatrick // Note: drop_view<input-range>::begin() is still trivially amortized O(1) because 6176d0caaeSpatrick // one can't call begin() on it more than once. 6276d0caaeSpatrick static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>); 6376d0caaeSpatrick using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; 64*4bdff4beSrobert _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); 6576d0caaeSpatrick range_difference_t<_View> __count_ = 0; 6676d0caaeSpatrick _View __base_ = _View(); 6776d0caaeSpatrick 6876d0caaeSpatrick public: 6976d0caaeSpatrick drop_view() requires default_initializable<_View> = default; 7076d0caaeSpatrick 7176d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI drop_view(_View __base,range_difference_t<_View> __count)7276d0caaeSpatrick constexpr drop_view(_View __base, range_difference_t<_View> __count) 7376d0caaeSpatrick : __count_(__count) 74*4bdff4beSrobert , __base_(std::move(__base)) 7576d0caaeSpatrick { 7676d0caaeSpatrick _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); 7776d0caaeSpatrick } 7876d0caaeSpatrick base()7976d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } base()80*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 8176d0caaeSpatrick 8276d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI begin()8376d0caaeSpatrick constexpr auto begin() 8476d0caaeSpatrick requires (!(__simple_view<_View> && 8576d0caaeSpatrick random_access_range<const _View> && sized_range<const _View>)) 8676d0caaeSpatrick { 8776d0caaeSpatrick if constexpr (_UseCache) 8876d0caaeSpatrick if (__cached_begin_.__has_value()) 8976d0caaeSpatrick return *__cached_begin_; 9076d0caaeSpatrick 9176d0caaeSpatrick auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); 9276d0caaeSpatrick if constexpr (_UseCache) 93*4bdff4beSrobert __cached_begin_.__emplace(__tmp); 9476d0caaeSpatrick return __tmp; 9576d0caaeSpatrick } 9676d0caaeSpatrick 9776d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI begin()9876d0caaeSpatrick constexpr auto begin() const 9976d0caaeSpatrick requires random_access_range<const _View> && sized_range<const _View> 10076d0caaeSpatrick { 10176d0caaeSpatrick return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); 10276d0caaeSpatrick } 10376d0caaeSpatrick 10476d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI end()10576d0caaeSpatrick constexpr auto end() 10676d0caaeSpatrick requires (!__simple_view<_View>) 10776d0caaeSpatrick { return ranges::end(__base_); } 10876d0caaeSpatrick 10976d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI end()11076d0caaeSpatrick constexpr auto end() const 11176d0caaeSpatrick requires range<const _View> 11276d0caaeSpatrick { return ranges::end(__base_); } 11376d0caaeSpatrick 11476d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI __size(auto & __self)11576d0caaeSpatrick static constexpr auto __size(auto& __self) { 11676d0caaeSpatrick const auto __s = ranges::size(__self.__base_); 11776d0caaeSpatrick const auto __c = static_cast<decltype(__s)>(__self.__count_); 11876d0caaeSpatrick return __s < __c ? 0 : __s - __c; 11976d0caaeSpatrick } 12076d0caaeSpatrick 12176d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI size()12276d0caaeSpatrick constexpr auto size() 12376d0caaeSpatrick requires sized_range<_View> 12476d0caaeSpatrick { return __size(*this); } 12576d0caaeSpatrick 12676d0caaeSpatrick _LIBCPP_HIDE_FROM_ABI size()12776d0caaeSpatrick constexpr auto size() const 12876d0caaeSpatrick requires sized_range<const _View> 12976d0caaeSpatrick { return __size(*this); } 13076d0caaeSpatrick }; 13176d0caaeSpatrick 13276d0caaeSpatrick template<class _Range> 13376d0caaeSpatrick drop_view(_Range&&, range_difference_t<_Range>) -> drop_view<views::all_t<_Range>>; 13476d0caaeSpatrick 13576d0caaeSpatrick template<class _Tp> 13676d0caaeSpatrick inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>; 137*4bdff4beSrobert 138*4bdff4beSrobert namespace views { 139*4bdff4beSrobert namespace __drop { 140*4bdff4beSrobert 141*4bdff4beSrobert template <class _Tp> 142*4bdff4beSrobert inline constexpr bool __is_empty_view = false; 143*4bdff4beSrobert 144*4bdff4beSrobert template <class _Tp> 145*4bdff4beSrobert inline constexpr bool __is_empty_view<empty_view<_Tp>> = true; 146*4bdff4beSrobert 147*4bdff4beSrobert template <class _Tp> 148*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization = false; 149*4bdff4beSrobert 150*4bdff4beSrobert template <class _Tp, size_t _Extent> 151*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<span<_Tp, _Extent>> = true; 152*4bdff4beSrobert 153*4bdff4beSrobert template <class _CharT, class _Traits> 154*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<basic_string_view<_CharT, _Traits>> = true; 155*4bdff4beSrobert 156*4bdff4beSrobert template <class _Np, class _Bound> 157*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<iota_view<_Np, _Bound>> = true; 158*4bdff4beSrobert 159*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind> 160*4bdff4beSrobert inline constexpr bool __is_passthrough_specialization<subrange<_Iter, _Sent, _Kind>> = 161*4bdff4beSrobert !subrange<_Iter, _Sent, _Kind>::_StoreSize; 162*4bdff4beSrobert 163*4bdff4beSrobert template <class _Tp> 164*4bdff4beSrobert inline constexpr bool __is_subrange_specialization_with_store_size = false; 165*4bdff4beSrobert 166*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind> 167*4bdff4beSrobert inline constexpr bool __is_subrange_specialization_with_store_size<subrange<_Iter, _Sent, _Kind>> = 168*4bdff4beSrobert subrange<_Iter, _Sent, _Kind>::_StoreSize; 169*4bdff4beSrobert 170*4bdff4beSrobert template <class _Tp> 171*4bdff4beSrobert struct __passthrough_type; 172*4bdff4beSrobert 173*4bdff4beSrobert template <class _Tp, size_t _Extent> 174*4bdff4beSrobert struct __passthrough_type<span<_Tp, _Extent>> { 175*4bdff4beSrobert using type = span<_Tp>; 176*4bdff4beSrobert }; 177*4bdff4beSrobert 178*4bdff4beSrobert template <class _CharT, class _Traits> 179*4bdff4beSrobert struct __passthrough_type<basic_string_view<_CharT, _Traits>> { 180*4bdff4beSrobert using type = basic_string_view<_CharT, _Traits>; 181*4bdff4beSrobert }; 182*4bdff4beSrobert 183*4bdff4beSrobert template <class _Np, class _Bound> 184*4bdff4beSrobert struct __passthrough_type<iota_view<_Np, _Bound>> { 185*4bdff4beSrobert using type = iota_view<_Np, _Bound>; 186*4bdff4beSrobert }; 187*4bdff4beSrobert 188*4bdff4beSrobert template <class _Iter, class _Sent, subrange_kind _Kind> 189*4bdff4beSrobert struct __passthrough_type<subrange<_Iter, _Sent, _Kind>> { 190*4bdff4beSrobert using type = subrange<_Iter, _Sent, _Kind>; 191*4bdff4beSrobert }; 192*4bdff4beSrobert 193*4bdff4beSrobert template <class _Tp> 194*4bdff4beSrobert using __passthrough_type_t = typename __passthrough_type<_Tp>::type; 195*4bdff4beSrobert 196*4bdff4beSrobert struct __fn { 197*4bdff4beSrobert // [range.drop.overview]: the `empty_view` case. 198*4bdff4beSrobert template <class _Range, convertible_to<range_difference_t<_Range>> _Np> 199*4bdff4beSrobert requires __is_empty_view<remove_cvref_t<_Range>> 200*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 201*4bdff4beSrobert constexpr auto operator()(_Range&& __range, _Np&&) const 202*4bdff4beSrobert noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) 203*4bdff4beSrobert -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) 204*4bdff4beSrobert { return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); } 205*4bdff4beSrobert 206*4bdff4beSrobert // [range.drop.overview]: the `span | basic_string_view | iota_view | subrange (StoreSize == false)` case. 207*4bdff4beSrobert template <class _Range, 208*4bdff4beSrobert convertible_to<range_difference_t<_Range>> _Np, 209*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>, 210*4bdff4beSrobert class _Dist = range_difference_t<_Range>> 211*4bdff4beSrobert requires (!__is_empty_view<_RawRange> && 212*4bdff4beSrobert random_access_range<_RawRange> && 213*4bdff4beSrobert sized_range<_RawRange> && 214*4bdff4beSrobert __is_passthrough_specialization<_RawRange>) 215*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 216*4bdff4beSrobert constexpr auto operator()(_Range&& __rng, _Np&& __n) const 217*4bdff4beSrobert noexcept(noexcept(__passthrough_type_t<_RawRange>( 218*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)), 219*4bdff4beSrobert ranges::end(__rng) 220*4bdff4beSrobert ))) 221*4bdff4beSrobert -> decltype( __passthrough_type_t<_RawRange>( 222*4bdff4beSrobert // Note: deliberately not forwarding `__rng` to guard against double moves. 223*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)), 224*4bdff4beSrobert ranges::end(__rng) 225*4bdff4beSrobert )) 226*4bdff4beSrobert { return __passthrough_type_t<_RawRange>( 227*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)), 228*4bdff4beSrobert ranges::end(__rng) 229*4bdff4beSrobert ); } 230*4bdff4beSrobert 231*4bdff4beSrobert // [range.drop.overview]: the `subrange (StoreSize == true)` case. 232*4bdff4beSrobert template <class _Range, 233*4bdff4beSrobert convertible_to<range_difference_t<_Range>> _Np, 234*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>, 235*4bdff4beSrobert class _Dist = range_difference_t<_Range>> 236*4bdff4beSrobert requires (!__is_empty_view<_RawRange> && 237*4bdff4beSrobert random_access_range<_RawRange> && 238*4bdff4beSrobert sized_range<_RawRange> && 239*4bdff4beSrobert __is_subrange_specialization_with_store_size<_RawRange>) 240*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 241*4bdff4beSrobert constexpr auto operator()(_Range&& __rng, _Np&& __n) const 242*4bdff4beSrobert noexcept(noexcept(_RawRange( 243*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)), 244*4bdff4beSrobert ranges::end(__rng), 245*4bdff4beSrobert std::__to_unsigned_like(ranges::distance(__rng) - 246*4bdff4beSrobert std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))) 247*4bdff4beSrobert ))) 248*4bdff4beSrobert -> decltype( _RawRange( 249*4bdff4beSrobert // Note: deliberately not forwarding `__rng` to guard against double moves. 250*4bdff4beSrobert ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)), 251*4bdff4beSrobert ranges::end(__rng), 252*4bdff4beSrobert std::__to_unsigned_like(ranges::distance(__rng) - 253*4bdff4beSrobert std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n))) 254*4bdff4beSrobert )) 255*4bdff4beSrobert { 256*4bdff4beSrobert // Introducing local variables avoids calculating `min` and `distance` twice (at the cost of diverging from the 257*4bdff4beSrobert // expression used in the `noexcept` clause and the return statement). 258*4bdff4beSrobert auto dist = ranges::distance(__rng); 259*4bdff4beSrobert auto clamped = std::min<_Dist>(dist, std::forward<_Np>(__n)); 260*4bdff4beSrobert return _RawRange( 261*4bdff4beSrobert ranges::begin(__rng) + clamped, 262*4bdff4beSrobert ranges::end(__rng), 263*4bdff4beSrobert std::__to_unsigned_like(dist - clamped) 264*4bdff4beSrobert );} 265*4bdff4beSrobert 266*4bdff4beSrobert // [range.drop.overview]: the "otherwise" case. 267*4bdff4beSrobert template <class _Range, convertible_to<range_difference_t<_Range>> _Np, 268*4bdff4beSrobert class _RawRange = remove_cvref_t<_Range>> 269*4bdff4beSrobert // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other 270*4bdff4beSrobert // overloads. 271*4bdff4beSrobert requires (!(__is_empty_view<_RawRange> || 272*4bdff4beSrobert (__is_subrange_specialization_with_store_size<_RawRange> && 273*4bdff4beSrobert sized_range<_RawRange> && 274*4bdff4beSrobert random_access_range<_RawRange>) || 275*4bdff4beSrobert (__is_passthrough_specialization<_RawRange> && 276*4bdff4beSrobert sized_range<_RawRange> && 277*4bdff4beSrobert random_access_range<_RawRange>) 278*4bdff4beSrobert )) 279*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 280*4bdff4beSrobert constexpr auto operator()(_Range&& __range, _Np&& __n) const 281*4bdff4beSrobert noexcept(noexcept(drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n)))) 282*4bdff4beSrobert -> decltype( drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n))) 283*4bdff4beSrobert { return drop_view(std::forward<_Range>(__range), std::forward<_Np>(__n)); } 284*4bdff4beSrobert 285*4bdff4beSrobert template <class _Np> 286*4bdff4beSrobert requires constructible_from<decay_t<_Np>, _Np> 287*4bdff4beSrobert [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 288*4bdff4beSrobert constexpr auto operator()(_Np&& __n) const 289*4bdff4beSrobert noexcept(is_nothrow_constructible_v<decay_t<_Np>, _Np>) 290*4bdff4beSrobert { return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Np>(__n))); } 291*4bdff4beSrobert }; 292*4bdff4beSrobert 293*4bdff4beSrobert } // namespace __drop 294*4bdff4beSrobert 295*4bdff4beSrobert inline namespace __cpo { 296*4bdff4beSrobert inline constexpr auto drop = __drop::__fn{}; 297*4bdff4beSrobert } // namespace __cpo 298*4bdff4beSrobert } // namespace views 299*4bdff4beSrobert 30076d0caaeSpatrick } // namespace ranges 30176d0caaeSpatrick 302*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17 30376d0caaeSpatrick 30476d0caaeSpatrick _LIBCPP_END_NAMESPACE_STD 30576d0caaeSpatrick 30676d0caaeSpatrick _LIBCPP_POP_MACROS 30776d0caaeSpatrick 30876d0caaeSpatrick #endif // _LIBCPP___RANGES_DROP_VIEW_H 309