xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/drop_view.h (revision d30a1689f5b37e78ea189232a8b94a7011dc0dc8)
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