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_LAST_HPP
0015 #define RANGES_V3_VIEW_DROP_LAST_HPP
0016
0017 #include <type_traits>
0018
0019 #include <meta/meta.hpp>
0020
0021 #include <range/v3/functional/bind_back.hpp>
0022 #include <range/v3/iterator/counted_iterator.hpp>
0023 #include <range/v3/iterator/default_sentinel.hpp>
0024 #include <range/v3/iterator/operations.hpp>
0025 #include <range/v3/range/access.hpp>
0026 #include <range/v3/range/concepts.hpp>
0027 #include <range/v3/range/primitives.hpp>
0028 #include <range/v3/utility/optional.hpp>
0029 #include <range/v3/utility/static_const.hpp>
0030 #include <range/v3/view/adaptor.hpp>
0031 #include <range/v3/view/all.hpp>
0032 #include <range/v3/view/interface.hpp>
0033 #include <range/v3/view/view.hpp>
0034
0035 #include <range/v3/detail/prologue.hpp>
0036
0037 namespace ranges
0038 {
0039
0040
0041
0042
0043 namespace detail
0044 {
0045 namespace drop_last_view
0046 {
0047 template<typename Rng>
0048 range_size_t<Rng> get_size(Rng & rng, range_difference_t<Rng> n_)
0049 {
0050 RANGES_EXPECT(n_ >= 0);
0051 range_size_t<Rng> const initial_size = ranges::size(rng);
0052 range_size_t<Rng> const n = static_cast<range_size_t<Rng>>(n_);
0053 return initial_size > n ? initial_size - n : 0;
0054 }
0055
0056 template(typename Rng)(
0057 requires random_access_range<Rng> AND sized_range<Rng>)
0058 iterator_t<Rng> get_end(Rng & rng, range_difference_t<Rng> n, int)
0059 {
0060 return begin(rng) + static_cast<range_difference_t<Rng>>(
0061 drop_last_view::get_size(rng, n));
0062 }
0063 template(typename Rng)(
0064 requires bidirectional_range<Rng> AND common_range<Rng>)
0065 iterator_t<Rng> get_end(Rng & rng, range_difference_t<Rng> n, long)
0066 {
0067 return prev(end(rng), n, begin(rng));
0068 }
0069
0070 enum class mode_enum
0071 {
0072 bidi,
0073 forward,
0074 sized,
0075 invalid
0076 };
0077
0078 template<mode_enum Mode>
0079 using mode_t = std::integral_constant<mode_enum, Mode>;
0080
0081 using mode_bidi = mode_t<mode_enum::bidi>;
0082 using mode_forward = mode_t<mode_enum::forward>;
0083 using mode_sized = mode_t<mode_enum::sized>;
0084 using mode_invalid = mode_t<mode_enum::invalid>;
0085
0086 template<typename Rng>
0087 constexpr mode_enum get_mode() noexcept
0088 {
0089
0090
0091 return (random_access_range<Rng> && view_<Rng> && sized_range<Rng>) ||
0092 (bidirectional_range<Rng> && view_<Rng> &&
0093 common_range<Rng>)
0094 ? mode_enum::bidi
0095 : sized_range<Rng> && view_<Rng>
0096 ? mode_enum::sized
0097 : forward_range<Rng> && view_<Rng>
0098 ? mode_enum::forward
0099 : mode_enum::invalid;
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 }
0111
0112 template<typename Rng>
0113 using mode_of = mode_t<drop_last_view::get_mode<Rng>()>;
0114 }
0115 }
0116
0117
0118 template<typename Rng, typename = detail::drop_last_view::mode_of<Rng>>
0119 struct drop_last_view
0120 {};
0121
0122 template<typename Rng>
0123 struct drop_last_view<Rng, detail::drop_last_view::mode_bidi>
0124 : view_interface<drop_last_view<Rng, detail::drop_last_view::mode_bidi>,
0125 is_finite<Rng>::value
0126 ? finite
0127 : range_cardinality<Rng>::value>
0128 {
0129 CPP_assert(
0130 (random_access_range<Rng> && view_<Rng> && sized_range<Rng>) ||
0131 (bidirectional_range<Rng> && view_<Rng> && common_range<Rng>));
0132
0133 private:
0134 friend range_access;
0135 using difference_t = range_difference_t<Rng>;
0136
0137 Rng rng_;
0138 difference_t n_;
0139 detail::non_propagating_cache<iterator_t<Rng>> end_;
0140
0141 public:
0142 drop_last_view() = default;
0143 constexpr drop_last_view(Rng rng, difference_t n)
0144 : rng_(std::move(rng))
0145 , n_(n)
0146 {
0147 RANGES_EXPECT(n >= 0);
0148 }
0149
0150 iterator_t<Rng> begin()
0151 {
0152 return ranges::begin(rng_);
0153 }
0154 sentinel_t<Rng> end()
0155 {
0156 if(!end_)
0157 end_ = detail::drop_last_view::get_end(rng_, n_, 0);
0158 return *end_;
0159 }
0160 template(typename CRng = Rng const)(
0161 requires random_access_range<CRng> AND sized_range<CRng>)
0162 iterator_t<CRng> begin() const
0163 {
0164 return ranges::begin(rng_);
0165 }
0166 template(typename CRng = Rng const)(
0167 requires random_access_range<CRng> AND sized_range<CRng>)
0168 iterator_t<CRng> end() const
0169 {
0170 return detail::drop_last_view::get_end(rng_, n_, 0);
0171 }
0172
0173 CPP_auto_member
0174 auto CPP_fun(size)()(
0175 requires sized_range<Rng>)
0176 {
0177 return detail::drop_last_view::get_size(rng_, n_);
0178 }
0179 CPP_auto_member
0180 auto CPP_fun(size)()(const
0181 requires sized_range<Rng const>)
0182 {
0183 return detail::drop_last_view::get_size(rng_, n_);
0184 }
0185
0186 Rng & base()
0187 {
0188 return rng_;
0189 }
0190 Rng const & base() const
0191 {
0192 return rng_;
0193 }
0194 };
0195
0196 template<typename Rng>
0197 struct drop_last_view<Rng, detail::drop_last_view::mode_forward>
0198 : view_adaptor<drop_last_view<Rng, detail::drop_last_view::mode_forward>, Rng,
0199 is_finite<Rng>::value
0200 ? finite
0201 : range_cardinality<Rng>::value>
0202
0203 {
0204 CPP_assert(forward_range<Rng> && view_<Rng>);
0205
0206 private:
0207 friend range_access;
0208
0209 using difference_t = range_difference_t<Rng>;
0210 difference_t n_;
0211 detail::non_propagating_cache<iterator_t<Rng>> probe_begin;
0212
0213 struct adaptor : adaptor_base
0214 {
0215 iterator_t<Rng> probe_;
0216
0217 adaptor() = default;
0218 adaptor(iterator_t<Rng> probe_first)
0219 : probe_(std::move(probe_first))
0220 {}
0221 void next(iterator_t<Rng> & it)
0222 {
0223 ++it;
0224 ++probe_;
0225 }
0226 };
0227
0228 struct sentinel_adaptor : adaptor_base
0229 {
0230 template<typename I, typename S>
0231 bool empty(I const &, adaptor const & ia, S const & s) const
0232 {
0233 return ia.probe_ == s;
0234 }
0235 };
0236
0237 adaptor begin_adaptor()
0238 {
0239 if(!probe_begin)
0240 probe_begin = next(begin(this->base()), n_, end(this->base()));
0241 return {*probe_begin};
0242 }
0243 sentinel_adaptor end_adaptor()
0244 {
0245 return {};
0246 }
0247
0248 public:
0249 drop_last_view() = default;
0250 constexpr drop_last_view(Rng rng, difference_t n)
0251 : drop_last_view::view_adaptor(std::move(rng))
0252 , n_(n)
0253 {
0254 RANGES_EXPECT(n >= 0);
0255 }
0256
0257 CPP_auto_member
0258 auto CPP_fun(size)()(
0259 requires sized_range<Rng>)
0260 {
0261 return detail::drop_last_view::get_size(this->base(), n_);
0262 }
0263 CPP_auto_member
0264 auto CPP_fun(size)()(const
0265 requires sized_range<Rng const>)
0266 {
0267 return detail::drop_last_view::get_size(this->base(), n_);
0268 }
0269 };
0270
0271 template<typename Rng>
0272 struct drop_last_view<Rng, detail::drop_last_view::mode_sized>
0273 : view_interface<drop_last_view<Rng, detail::drop_last_view::mode_sized>, finite>
0274 {
0275 CPP_assert(sized_range<Rng> && view_<Rng>);
0276
0277 private:
0278 friend range_access;
0279
0280 using difference_t = range_difference_t<Rng>;
0281 Rng rng_;
0282 difference_t n_;
0283
0284 public:
0285 drop_last_view() = default;
0286 constexpr drop_last_view(Rng rng, difference_t n)
0287 : rng_(std::move(rng))
0288 , n_(n)
0289 {
0290 RANGES_EXPECT(n >= 0);
0291 }
0292
0293 counted_iterator<iterator_t<Rng>> begin()
0294 {
0295 return {ranges::begin(rng_), static_cast<difference_t>(size())};
0296 }
0297 template(typename CRng = Rng const)(
0298 requires sized_range<CRng>)
0299 counted_iterator<iterator_t<CRng>> begin() const
0300 {
0301 return {ranges::begin(rng_), static_cast<difference_t>(size())};
0302 }
0303 default_sentinel_t end() const
0304 {
0305 return {};
0306 }
0307 range_size_t<Rng> size()
0308 {
0309 return detail::drop_last_view::get_size(this->base(), n_);
0310 }
0311 CPP_auto_member
0312 auto CPP_fun(size)()(const
0313 requires sized_range<Rng const>)
0314 {
0315 return detail::drop_last_view::get_size(this->base(), n_);
0316 }
0317
0318 Rng & base()
0319 {
0320 return rng_;
0321 }
0322 Rng const & base() const
0323 {
0324 return rng_;
0325 }
0326 };
0327
0328 template<typename Rng, typename T>
0329 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<drop_last_view<Rng, T>> =
0330 enable_borrowed_range<Rng>;
0331
0332 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0333 template<typename Rng>
0334 drop_last_view(Rng &&, range_difference_t<Rng>)
0335 -> drop_last_view<views::all_t<Rng>>;
0336 #endif
0337
0338 namespace views
0339 {
0340 struct drop_last_base_fn
0341 {
0342 template(typename Rng)(
0343 requires sized_range<Rng> || forward_range<Rng>)
0344 constexpr auto operator()(Rng && rng, range_difference_t<Rng> n) const
0345 -> drop_last_view<all_t<Rng>>
0346 {
0347 return {all(static_cast<Rng &&>(rng)), n};
0348 }
0349 };
0350
0351 struct drop_last_fn : drop_last_base_fn
0352 {
0353 using drop_last_base_fn::operator();
0354
0355 template(typename Int)(
0356 requires detail::integer_like_<Int>)
0357 constexpr auto operator()(Int n) const
0358 {
0359 return make_view_closure(bind_back(drop_last_base_fn{}, n));
0360 }
0361 };
0362
0363 RANGES_INLINE_VARIABLE(drop_last_fn, drop_last)
0364 }
0365
0366
0367 }
0368
0369 #include <range/v3/detail/epilogue.hpp>
0370 #include <range/v3/detail/satisfy_boost_range.hpp>
0371 RANGES_SATISFY_BOOST_RANGE(::ranges::drop_last_view)
0372
0373 #endif