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_DROP_VIEW_H 10 #define _LIBCPP___RANGES_DROP_VIEW_H 11 12 #include <__config> 13 #include <__debug> 14 #include <__iterator/concepts.h> 15 #include <__iterator/iterator_traits.h> 16 #include <__iterator/next.h> 17 #include <__ranges/access.h> 18 #include <__ranges/all.h> 19 #include <__ranges/concepts.h> 20 #include <__ranges/enable_borrowed_range.h> 21 #include <__ranges/non_propagating_cache.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_BEGIN_NAMESPACE_STD 33 34 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 35 36 namespace ranges { 37 template<view _View> 38 class drop_view 39 : public view_interface<drop_view<_View>> 40 { 41 // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an 42 // amortized O(1) begin() method. If this is an input_range, then we cannot cache 43 // begin because begin is not equality preserving. 44 // Note: drop_view<input-range>::begin() is still trivially amortized O(1) because 45 // one can't call begin() on it more than once. 46 static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>); 47 using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; 48 [[no_unique_address]] _Cache __cached_begin_ = _Cache(); 49 range_difference_t<_View> __count_ = 0; 50 _View __base_ = _View(); 51 52 public: 53 drop_view() requires default_initializable<_View> = default; 54 55 _LIBCPP_HIDE_FROM_ABI 56 constexpr drop_view(_View __base, range_difference_t<_View> __count) 57 : __count_(__count) 58 , __base_(_VSTD::move(__base)) 59 { 60 _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); 61 } 62 63 _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } 64 _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return _VSTD::move(__base_); } 65 66 _LIBCPP_HIDE_FROM_ABI 67 constexpr auto begin() 68 requires (!(__simple_view<_View> && 69 random_access_range<const _View> && sized_range<const _View>)) 70 { 71 if constexpr (_UseCache) 72 if (__cached_begin_.__has_value()) 73 return *__cached_begin_; 74 75 auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); 76 if constexpr (_UseCache) 77 __cached_begin_.__emplace(__tmp); 78 return __tmp; 79 } 80 81 _LIBCPP_HIDE_FROM_ABI 82 constexpr auto begin() const 83 requires random_access_range<const _View> && sized_range<const _View> 84 { 85 return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); 86 } 87 88 _LIBCPP_HIDE_FROM_ABI 89 constexpr auto end() 90 requires (!__simple_view<_View>) 91 { return ranges::end(__base_); } 92 93 _LIBCPP_HIDE_FROM_ABI 94 constexpr auto end() const 95 requires range<const _View> 96 { return ranges::end(__base_); } 97 98 _LIBCPP_HIDE_FROM_ABI 99 static constexpr auto __size(auto& __self) { 100 const auto __s = ranges::size(__self.__base_); 101 const auto __c = static_cast<decltype(__s)>(__self.__count_); 102 return __s < __c ? 0 : __s - __c; 103 } 104 105 _LIBCPP_HIDE_FROM_ABI 106 constexpr auto size() 107 requires sized_range<_View> 108 { return __size(*this); } 109 110 _LIBCPP_HIDE_FROM_ABI 111 constexpr auto size() const 112 requires sized_range<const _View> 113 { return __size(*this); } 114 }; 115 116 template<class _Range> 117 drop_view(_Range&&, range_difference_t<_Range>) -> drop_view<views::all_t<_Range>>; 118 119 template<class _Tp> 120 inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>; 121 } // namespace ranges 122 123 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 124 125 _LIBCPP_END_NAMESPACE_STD 126 127 #endif // _LIBCPP___RANGES_DROP_VIEW_H 128