File indexing completed on 2025-01-18 10:09:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_DROP_HPP
0015 #define RANGES_V3_VIEW_DROP_HPP
0016
0017 #include <type_traits>
0018
0019 #include <meta/meta.hpp>
0020
0021 #include <range/v3/range_fwd.hpp>
0022
0023 #include <range/v3/algorithm/min.hpp>
0024 #include <range/v3/functional/bind_back.hpp>
0025 #include <range/v3/iterator/operations.hpp>
0026 #include <range/v3/iterator/traits.hpp>
0027 #include <range/v3/range/concepts.hpp>
0028 #include <range/v3/range/traits.hpp>
0029 #include <range/v3/utility/box.hpp>
0030 #include <range/v3/utility/optional.hpp>
0031 #include <range/v3/utility/static_const.hpp>
0032 #include <range/v3/view/all.hpp>
0033 #include <range/v3/view/interface.hpp>
0034 #include <range/v3/view/subrange.hpp>
0035 #include <range/v3/view/view.hpp>
0036
0037 #include <range/v3/detail/prologue.hpp>
0038
0039 namespace ranges
0040 {
0041
0042
0043 template<typename Rng>
0044 struct RANGES_EMPTY_BASES drop_view
0045 : view_interface<drop_view<Rng>,
0046 is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
0047 , private detail::non_propagating_cache<iterator_t<Rng>, drop_view<Rng>,
0048 !random_access_range<Rng>>
0049 {
0050 private:
0051 using difference_type_ = range_difference_t<Rng>;
0052 Rng rng_;
0053 difference_type_ n_;
0054
0055 template(bool Const = true)(
0056 requires Const AND range<meta::const_if_c<Const, Rng>>)
0057 iterator_t<meta::const_if_c<Const, Rng>>
0058 get_begin_(std::true_type, std::true_type) const
0059 {
0060 CPP_assert(random_access_range<meta::const_if_c<Const, Rng>>);
0061 return next(ranges::begin(rng_), n_, ranges::end(rng_));
0062 }
0063 iterator_t<Rng> get_begin_(std::true_type, std::false_type)
0064 {
0065 CPP_assert(random_access_range<Rng>);
0066 return next(ranges::begin(rng_), n_, ranges::end(rng_));
0067 }
0068 iterator_t<Rng> get_begin_(std::false_type, detail::ignore_t)
0069 {
0070 CPP_assert(!random_access_range<Rng>);
0071 using cache_t =
0072 detail::non_propagating_cache<iterator_t<Rng>, drop_view<Rng>>;
0073 auto & begin_ = static_cast<cache_t &>(*this);
0074 if(!begin_)
0075 begin_ = next(ranges::begin(rng_), n_, ranges::end(rng_));
0076 return *begin_;
0077 }
0078
0079 public:
0080 drop_view() = default;
0081 drop_view(Rng rng, difference_type_ n)
0082 : rng_(std::move(rng))
0083 , n_(n)
0084 {
0085 RANGES_EXPECT(n >= 0);
0086 }
0087 iterator_t<Rng> begin()
0088 {
0089 return this->get_begin_(meta::bool_<random_access_range<Rng>>{},
0090 std::false_type{});
0091 }
0092 sentinel_t<Rng> end()
0093 {
0094 return ranges::end(rng_);
0095 }
0096 template(bool Const = true)(
0097 requires Const AND random_access_range<meta::const_if_c<Const, Rng>>)
0098 iterator_t<meta::const_if_c<Const, Rng>> begin() const
0099 {
0100 return this->get_begin_(std::true_type{}, std::true_type{});
0101 }
0102 template(bool Const = true)(
0103 requires Const AND random_access_range<meta::const_if_c<Const, Rng>>)
0104 sentinel_t<meta::const_if_c<Const, Rng>> end() const
0105 {
0106 return ranges::end(rng_);
0107 }
0108 CPP_auto_member
0109 auto CPP_fun(size)()(const
0110 requires sized_range<Rng const>)
0111 {
0112 auto const s = ranges::size(rng_);
0113 auto const n = static_cast<range_size_t<Rng const>>(n_);
0114 return s < n ? 0 : s - n;
0115 }
0116 CPP_auto_member
0117 auto CPP_fun(size)()(
0118 requires sized_range<Rng>)
0119 {
0120 auto const s = ranges::size(rng_);
0121 auto const n = static_cast<range_size_t<Rng>>(n_);
0122 return s < n ? 0 : s - n;
0123 }
0124 Rng base() const
0125 {
0126 return rng_;
0127 }
0128 };
0129
0130 template<typename Rng>
0131 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<drop_view<Rng>> =
0132 enable_borrowed_range<Rng>;
0133
0134 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0135 template<typename Rng>
0136 drop_view(Rng &&, range_difference_t<Rng>)
0137 -> drop_view<views::all_t<Rng>>;
0138 #endif
0139
0140 namespace views
0141 {
0142 struct drop_base_fn
0143 {
0144 private:
0145 template<typename Rng>
0146 static auto impl_(Rng && rng, range_difference_t<Rng> n, input_range_tag)
0147 -> drop_view<all_t<Rng>>
0148 {
0149 return {all(static_cast<Rng &&>(rng)), n};
0150 }
0151 template(typename Rng)(
0152 requires borrowed_range<Rng> AND sized_range<Rng>)
0153 static subrange<iterator_t<Rng>, sentinel_t<Rng>>
0154 impl_(Rng && rng, range_difference_t<Rng> n, random_access_range_tag)
0155 {
0156 return {begin(rng) + ranges::min(n, distance(rng)), end(rng)};
0157 }
0158
0159 public:
0160 template(typename Rng)(
0161 requires viewable_range<Rng> AND input_range<Rng>)
0162 auto operator()(Rng && rng, range_difference_t<Rng> n) const
0163 {
0164 return drop_base_fn::impl_(
0165 static_cast<Rng &&>(rng), n, range_tag_of<Rng>{});
0166 }
0167 };
0168
0169 struct drop_fn : drop_base_fn
0170 {
0171 using drop_base_fn::operator();
0172
0173 template(typename Int)(
0174 requires detail::integer_like_<Int>)
0175 constexpr auto operator()(Int n) const
0176 {
0177 return make_view_closure(bind_back(drop_base_fn{}, n));
0178 }
0179 };
0180
0181
0182
0183 RANGES_INLINE_VARIABLE(drop_fn, drop)
0184 }
0185
0186 namespace cpp20
0187 {
0188 namespace views
0189 {
0190 using ranges::views::drop;
0191 }
0192 template(typename Rng)(
0193 requires view_<Rng>)
0194 using drop_view = ranges::drop_view<Rng>;
0195 }
0196
0197 }
0198
0199 #include <range/v3/detail/epilogue.hpp>
0200 #include <range/v3/detail/satisfy_boost_range.hpp>
0201 RANGES_SATISFY_BOOST_RANGE(::ranges::drop_view)
0202
0203 #endif