File indexing completed on 2025-01-18 10:09:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_SLICE_HPP
0015 #define RANGES_V3_VIEW_SLICE_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/functional/bind_back.hpp>
0024 #include <range/v3/iterator/counted_iterator.hpp>
0025 #include <range/v3/iterator/default_sentinel.hpp>
0026 #include <range/v3/iterator/operations.hpp>
0027 #include <range/v3/iterator/traits.hpp>
0028 #include <range/v3/range/concepts.hpp>
0029 #include <range/v3/range/traits.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/drop_exactly.hpp>
0034 #include <range/v3/view/facade.hpp>
0035 #include <range/v3/view/subrange.hpp>
0036 #include <range/v3/view/view.hpp>
0037
0038 #include <range/v3/detail/prologue.hpp>
0039
0040 namespace ranges
0041 {
0042
0043 namespace detail
0044 {
0045 template<typename Rng, typename Int>
0046 iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::true_type)
0047 {
0048 RANGES_EXPECT(0 <= i);
0049 return next(ranges::begin(rng), i);
0050 }
0051
0052 template<typename Rng, typename Int>
0053 iterator_t<Rng> pos_at_(Rng && rng, Int i, bidirectional_range_tag,
0054 std::false_type)
0055 {
0056 if(0 > i)
0057 {
0058
0059 if(RANGES_CONSTEXPR_IF(sized_range<Rng> && !common_range<Rng>))
0060 return next(ranges::begin(rng), distance(rng) + i);
0061
0062 return next(ranges::next(ranges::begin(rng), ranges::end(rng)), i);
0063 }
0064 return next(ranges::begin(rng), i);
0065 }
0066
0067 template<typename Rng, typename Int>
0068 iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::false_type)
0069 {
0070 RANGES_EXPECT(i >= 0 || (bool)sized_range<Rng> || (bool)forward_range<Rng>);
0071 if(0 > i)
0072 return next(ranges::begin(rng), distance(rng) + i);
0073 return next(ranges::begin(rng), i);
0074 }
0075
0076 template<typename Rng, bool IsRandomAccess>
0077 struct slice_view_ : view_facade<slice_view<Rng>, finite>
0078 {
0079 private:
0080 friend range_access;
0081 Rng rng_;
0082 range_difference_t<Rng> from_, count_;
0083 detail::non_propagating_cache<iterator_t<Rng>> begin_;
0084
0085 iterator_t<Rng> get_begin_()
0086 {
0087 if(!begin_)
0088 begin_ = detail::pos_at_(
0089 rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0090 return *begin_;
0091 }
0092
0093 public:
0094 slice_view_() = default;
0095 constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
0096 range_difference_t<Rng> count)
0097 : rng_(std::move(rng))
0098 , from_(from)
0099 , count_(count)
0100 {}
0101 counted_iterator<iterator_t<Rng>> begin()
0102 {
0103 return make_counted_iterator(get_begin_(), count_);
0104 }
0105 default_sentinel_t end()
0106 {
0107 return {};
0108 }
0109 auto size() const
0110 {
0111 return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
0112 }
0113 Rng base() const
0114 {
0115 return rng_;
0116 }
0117 };
0118
0119 template<typename Rng>
0120 struct slice_view_<Rng, true> : view_interface<slice_view<Rng>, finite>
0121 {
0122 private:
0123 Rng rng_;
0124 range_difference_t<Rng> from_, count_;
0125
0126 public:
0127 slice_view_() = default;
0128 constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
0129 range_difference_t<Rng> count)
0130 : rng_(std::move(rng))
0131 , from_(from)
0132 , count_(count)
0133 {
0134 RANGES_EXPECT(0 <= count_);
0135 }
0136 iterator_t<Rng> begin()
0137 {
0138 return detail::pos_at_(
0139 rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0140 }
0141 iterator_t<Rng> end()
0142 {
0143 return detail::pos_at_(
0144 rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
0145 count_;
0146 }
0147 template(typename BaseRng = Rng)(
0148 requires range<BaseRng const>)
0149 iterator_t<BaseRng const> begin() const
0150 {
0151 return detail::pos_at_(
0152 rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0153 }
0154 template(typename BaseRng = Rng)(
0155 requires range<BaseRng const>)
0156 iterator_t<BaseRng const> end() const
0157 {
0158 return detail::pos_at_(
0159 rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
0160 count_;
0161 }
0162 auto size() const
0163 {
0164 return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
0165 }
0166 Rng base() const
0167 {
0168 return rng_;
0169 }
0170 };
0171 }
0172
0173
0174
0175
0176 template<typename Rng>
0177 struct slice_view : detail::slice_view_<Rng, (bool)random_access_range<Rng>>
0178 {
0179 using detail::slice_view_<Rng, (bool)random_access_range<Rng>>::slice_view_;
0180 };
0181
0182 template<typename Rng>
0183 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<slice_view<Rng>> =
0184 enable_borrowed_range<Rng>;
0185
0186 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0187 template<typename Rng>
0188 slice_view(Rng &&, range_difference_t<Rng>, range_difference_t<Rng>)
0189 ->slice_view<views::all_t<Rng>>;
0190 #endif
0191
0192 namespace views
0193 {
0194 struct slice_base_fn
0195 {
0196 private:
0197 template<typename Rng>
0198 static constexpr slice_view<all_t<Rng>> impl_(Rng && rng,
0199 range_difference_t<Rng> from,
0200 range_difference_t<Rng> count,
0201 input_range_tag, range_tag = {})
0202 {
0203 return {all(static_cast<Rng &&>(rng)), from, count};
0204 }
0205 template(typename Rng)(
0206 requires borrowed_range<Rng>)
0207 static subrange<iterator_t<Rng>> impl_(Rng && rng,
0208 range_difference_t<Rng> from,
0209 range_difference_t<Rng> count,
0210 random_access_range_tag,
0211 common_range_tag = {})
0212 {
0213 auto it =
0214 detail::pos_at_(rng, from, range_tag_of<Rng>{}, is_infinite<Rng>{});
0215 return {it, it + count};
0216 }
0217
0218 public:
0219
0220 template(typename Rng)(
0221 requires viewable_range<Rng> AND input_range<Rng>)
0222 constexpr auto operator()(Rng && rng,
0223 range_difference_t<Rng> from,
0224 range_difference_t<Rng> to) const
0225 {
0226 RANGES_EXPECT(0 <= from && from <= to);
0227 return slice_base_fn::impl_(
0228 static_cast<Rng &&>(rng), from, to - from, range_tag_of<Rng>{});
0229 }
0230
0231
0232
0233 template(typename Rng)(
0234 requires viewable_range<Rng> AND input_range<Rng> AND sized_range<Rng>)
0235 auto operator()(Rng && rng,
0236 range_difference_t<Rng> from,
0237 detail::from_end_of_t<Rng> to) const
0238 {
0239 static_assert(!is_infinite<Rng>::value,
0240 "Can't index from the end of an infinite range!");
0241 RANGES_EXPECT(0 <= from);
0242 RANGES_ASSERT(from <= distance(rng) + to.dist_);
0243 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0244 from,
0245 distance(rng) + to.dist_ - from,
0246 range_tag_of<Rng>{});
0247 }
0248
0249 template(typename Rng)(
0250 requires viewable_range<Rng> AND
0251 (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
0252 auto operator()(Rng && rng,
0253 detail::from_end_of_t<Rng> from,
0254 detail::from_end_of_t<Rng> to) const
0255 {
0256 static_assert(!is_infinite<Rng>::value,
0257 "Can't index from the end of an infinite range!");
0258 RANGES_EXPECT(from.dist_ <= to.dist_);
0259 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0260 from.dist_,
0261 to.dist_ - from.dist_,
0262 range_tag_of<Rng>{},
0263 common_range_tag_of<Rng>{});
0264 }
0265
0266 template(typename Rng)(
0267 requires viewable_range<Rng> AND input_range<Rng>)
0268 auto operator()(Rng && rng, range_difference_t<Rng> from, end_fn) const
0269 {
0270 RANGES_EXPECT(0 <= from);
0271 return ranges::views::drop_exactly(static_cast<Rng &&>(rng), from);
0272 }
0273
0274 template(typename Rng)(
0275 requires viewable_range<Rng> AND
0276 (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
0277 auto operator()(Rng && rng,
0278 detail::from_end_of_t<Rng> from,
0279 end_fn) const
0280 {
0281 static_assert(!is_infinite<Rng>::value,
0282 "Can't index from the end of an infinite range!");
0283 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0284 from.dist_,
0285 -from.dist_,
0286 range_tag_of<Rng>{},
0287 common_range_tag_of<Rng>{});
0288 }
0289 };
0290
0291 struct slice_fn : slice_base_fn
0292 {
0293 using slice_base_fn::operator();
0294
0295
0296 template(typename Int)(
0297 requires detail::integer_like_<Int>)
0298 constexpr auto operator()(Int from, Int to) const
0299 {
0300 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0301 }
0302 template(typename Int)(
0303 requires detail::integer_like_<Int>)
0304 constexpr auto operator()(Int from, detail::from_end_<Int> to) const
0305 {
0306 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0307 }
0308 template(typename Int)(
0309 requires detail::integer_like_<Int>)
0310 constexpr auto operator()(detail::from_end_<Int> from,
0311 detail::from_end_<Int> to) const
0312 {
0313 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0314 }
0315 template(typename Int)(
0316 requires detail::integer_like_<Int>)
0317 constexpr auto operator()(Int from, end_fn) const
0318 {
0319 return make_view_closure(
0320 bind_back(ranges::views::drop_exactly_base_fn{}, from));
0321 }
0322 template(typename Int)(
0323 requires detail::integer_like_<Int>)
0324 constexpr auto operator()(detail::from_end_<Int> from, end_fn to) const
0325 {
0326 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0327 }
0328 };
0329
0330
0331
0332 RANGES_INLINE_VARIABLE(slice_fn, slice)
0333 }
0334
0335 }
0336
0337 #include <range/v3/detail/epilogue.hpp>
0338 #include <range/v3/detail/satisfy_boost_range.hpp>
0339 RANGES_SATISFY_BOOST_RANGE(::ranges::slice_view)
0340
0341 #endif