File indexing completed on 2025-12-15 10:26:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RANGES_V3_ITERATOR_OPERATIONS_HPP
0014 #define RANGES_V3_ITERATOR_OPERATIONS_HPP
0015
0016 #include <type_traits>
0017 #include <utility>
0018
0019 #include <range/v3/range_fwd.hpp>
0020
0021 #include <range/v3/iterator/concepts.hpp>
0022 #include <range/v3/iterator/traits.hpp>
0023 #include <range/v3/range/concepts.hpp>
0024
0025 #include <range/v3/detail/prologue.hpp>
0026
0027 namespace ranges
0028 {
0029
0030
0031
0032
0033 template<typename I>
0034
0035 struct counted_iterator;
0036
0037
0038 struct advance_fn
0039 {
0040 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0041 template(typename I)(
0042 requires input_or_output_iterator<I>)
0043 constexpr void operator()(I & i, iter_difference_t<I> n) const
0044
0045 {
0046 if constexpr(random_access_iterator<I>)
0047 {
0048 i += n;
0049 }
0050 else
0051 {
0052 if constexpr(bidirectional_iterator<I>)
0053 for(; 0 > n; ++n)
0054 --i;
0055 RANGES_EXPECT(0 <= n);
0056 for(; 0 < n; --n)
0057 ++i;
0058 }
0059 }
0060
0061 template(typename I, typename S)(
0062 requires sentinel_for<S, I>)
0063 constexpr void operator()(I & i, S bound) const
0064
0065 {
0066 if constexpr(assignable_from<I &, S>)
0067 {
0068 i = std::move(bound);
0069 }
0070 else if constexpr(sized_sentinel_for<S, I>)
0071 {
0072 iter_difference_t<I> d = bound - i;
0073 RANGES_EXPECT(0 <= d);
0074 (*this)(i, d);
0075 }
0076 else
0077 while(i != bound)
0078 ++i;
0079 }
0080
0081 template(typename I, typename S)(
0082 requires sentinel_for<S, I>)
0083 constexpr iter_difference_t<I>
0084 operator()(I & i, iter_difference_t<I> n, S bound) const
0085
0086
0087
0088
0089 {
0090 if constexpr(sized_sentinel_for<S, I>)
0091 {
0092 if(0 == n)
0093 return 0;
0094 const auto d = bound - i;
0095 if constexpr(bidirectional_iterator<I> && same_as<I, S>)
0096 {
0097 RANGES_EXPECT(0 <= n ? 0 <= d : 0 >= d);
0098 if(0 <= n ? d <= n : d >= n)
0099 {
0100 i = std::move(bound);
0101 return n - d;
0102 }
0103 }
0104 else
0105 {
0106 RANGES_EXPECT(0 <= n && 0 <= d);
0107 if(d <= n)
0108 {
0109 (*this)(i, std::move(bound));
0110 return n - d;
0111 }
0112 }
0113 (*this)(i, n);
0114 return 0;
0115 }
0116 else
0117 {
0118 if constexpr(bidirectional_iterator<I> && same_as<I, S>)
0119 {
0120 if(0 > n)
0121 {
0122 do
0123 {
0124 --i;
0125 ++n;
0126 } while(0 != n && i != bound);
0127 return n;
0128 }
0129 }
0130 RANGES_EXPECT(0 <= n);
0131 while(0 != n && i != bound)
0132 {
0133 ++i;
0134 --n;
0135 }
0136 return n;
0137 }
0138 }
0139 #else
0140 private:
0141 template<typename I>
0142 static constexpr void n_(I & i, iter_difference_t<I> n, std::input_iterator_tag);
0143 template<typename I>
0144 static constexpr void n_(I & i, iter_difference_t<I> n,
0145 std::bidirectional_iterator_tag);
0146 template<typename I>
0147 static constexpr void n_(I & i, iter_difference_t<I> n,
0148 std::random_access_iterator_tag);
0149 template<typename I, typename S>
0150 static constexpr void to_impl_(I & i, S s, sentinel_tag);
0151 template<typename I, typename S>
0152 static constexpr void to_impl_(I & i, S s, sized_sentinel_tag);
0153 template<typename I, typename S>
0154 static constexpr void to_(I & i, S s, std::true_type);
0155 template<typename I, typename S>
0156 static constexpr void to_(I & i, S s, std::false_type);
0157 template<typename I, typename S>
0158 static constexpr iter_difference_t<I> bounded_(I & it, iter_difference_t<I> n,
0159 S bound, sentinel_tag,
0160 std::input_iterator_tag);
0161 template<typename I>
0162 static constexpr iter_difference_t<I> bounded_(I & it, iter_difference_t<I> n,
0163 I bound, sentinel_tag,
0164 std::bidirectional_iterator_tag);
0165 template<typename I, typename S, typename Concept>
0166 static constexpr iter_difference_t<I> bounded_(I & it, iter_difference_t<I> n,
0167 S bound, sized_sentinel_tag,
0168 Concept);
0169
0170 public:
0171
0172 template(typename I)(
0173 requires input_or_output_iterator<I>)
0174 constexpr void operator()(I & i, iter_difference_t<I> n) const
0175 {
0176 advance_fn::n_(i, n, iterator_tag_of<I>{});
0177 }
0178
0179 template(typename I, typename S)(
0180 requires sentinel_for<S, I>)
0181 constexpr void operator()(I & i, S s) const
0182 {
0183 advance_fn::to_(
0184 i, static_cast<S &&>(s), meta::bool_<assignable_from<I &, S>>());
0185 }
0186
0187 template(typename I, typename S)(
0188 requires sentinel_for<S, I>)
0189 constexpr iter_difference_t<I>
0190 operator()(I & it, iter_difference_t<I> n, S bound) const
0191 {
0192 return advance_fn::bounded_(it,
0193 n,
0194 static_cast<S &&>(bound),
0195 sentinel_tag_of<S, I>(),
0196 iterator_tag_of<I>());
0197 }
0198 #endif
0199
0200 template(typename I)(
0201 requires input_or_output_iterator<I>)
0202 constexpr void operator()(counted_iterator<I> & i, iter_difference_t<I> n) const;
0203 };
0204
0205
0206 RANGES_INLINE_VARIABLE(advance_fn, advance)
0207
0208 #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
0209 template<typename I>
0210 constexpr void advance_fn::n_(I & i, iter_difference_t<I> n, std::input_iterator_tag)
0211 {
0212 RANGES_EXPECT(n >= 0);
0213 for(; n > 0; --n)
0214 ++i;
0215 }
0216 template<typename I>
0217 constexpr void advance_fn::n_(I & i, iter_difference_t<I> n,
0218 std::bidirectional_iterator_tag)
0219 {
0220 if(n > 0)
0221 for(; n > 0; --n)
0222 ++i;
0223 else
0224 for(; n < 0; ++n)
0225 --i;
0226 }
0227 template<typename I>
0228 constexpr void advance_fn::n_(I & i, iter_difference_t<I> n,
0229 std::random_access_iterator_tag)
0230 {
0231 i += n;
0232 }
0233 template<typename I, typename S>
0234 constexpr void advance_fn::to_impl_(I & i, S s, sentinel_tag)
0235 {
0236 while(i != s)
0237 ++i;
0238 }
0239 template<typename I, typename S>
0240 constexpr void advance_fn::to_impl_(I & i, S s, sized_sentinel_tag)
0241 {
0242 iter_difference_t<I> d = s - i;
0243 RANGES_EXPECT(0 <= d);
0244 advance(i, d);
0245 }
0246
0247 template<typename I, typename S>
0248 constexpr void advance_fn::to_(I & i, S s, std::true_type)
0249 {
0250 i = static_cast<S &&>(s);
0251 }
0252 template<typename I, typename S>
0253 constexpr void advance_fn::to_(I & i, S s, std::false_type)
0254 {
0255 advance_fn::to_impl_(i, static_cast<S &&>(s), sentinel_tag_of<S, I>());
0256 }
0257 template<typename I, typename S>
0258 constexpr iter_difference_t<I> advance_fn::bounded_(I & it, iter_difference_t<I> n,
0259 S bound, sentinel_tag,
0260 std::input_iterator_tag)
0261 {
0262 RANGES_EXPECT(0 <= n);
0263 for(; 0 != n && it != bound; --n)
0264 ++it;
0265 return n;
0266 }
0267 template<typename I>
0268 constexpr iter_difference_t<I> advance_fn::bounded_(I & it, iter_difference_t<I> n,
0269 I bound, sentinel_tag,
0270 std::bidirectional_iterator_tag)
0271 {
0272 if(0 <= n)
0273 for(; 0 != n && it != bound; --n)
0274 ++it;
0275 else
0276 for(; 0 != n && it != bound; ++n)
0277 --it;
0278 return n;
0279 }
0280 template<typename I, typename S, typename Concept>
0281 constexpr iter_difference_t<I> advance_fn::bounded_(I & it, iter_difference_t<I> n,
0282 S bound, sized_sentinel_tag,
0283 Concept)
0284 {
0285 RANGES_EXPECT(((bool)same_as<I, S> || 0 <= n));
0286 if(n == 0)
0287 return 0;
0288 iter_difference_t<I> d = bound - it;
0289 RANGES_EXPECT(0 <= n ? 0 <= d : 0 >= d);
0290 if(0 <= n ? n >= d : n <= d)
0291 {
0292 advance(it, static_cast<S &&>(bound));
0293 return n - d;
0294 }
0295 advance(it, n);
0296 return 0;
0297 }
0298 #endif
0299
0300 struct next_fn
0301 {
0302 template(typename I)(
0303 requires input_or_output_iterator<I>)
0304 constexpr I operator()(I it) const
0305 {
0306 return ++it;
0307 }
0308 template(typename I)(
0309 requires input_or_output_iterator<I>)
0310 constexpr I operator()(I it, iter_difference_t<I> n) const
0311 {
0312 advance(it, n);
0313 return it;
0314 }
0315 template(typename I, typename S)(
0316 requires sentinel_for<S, I>)
0317 constexpr I operator()(I it, S s) const
0318 {
0319 advance(it, static_cast<S &&>(s));
0320 return it;
0321 }
0322 template(typename I, typename S)(
0323 requires sentinel_for<S, I>)
0324 constexpr I operator()(I it, iter_difference_t<I> n, S bound) const
0325 {
0326 advance(it, n, static_cast<S &&>(bound));
0327 return it;
0328 }
0329 };
0330
0331
0332 RANGES_INLINE_VARIABLE(next_fn, next)
0333
0334 struct prev_fn
0335 {
0336 template(typename I)(
0337 requires bidirectional_iterator<I>)
0338 constexpr I operator()(I it) const
0339 {
0340 return --it;
0341 }
0342 template(typename I)(
0343 requires bidirectional_iterator<I>)
0344 constexpr I operator()(I it, iter_difference_t<I> n) const
0345 {
0346 advance(it, -n);
0347 return it;
0348 }
0349 template(typename I)(
0350 requires bidirectional_iterator<I>)
0351 constexpr I operator()(I it, iter_difference_t<I> n, I bound) const
0352 {
0353 advance(it, -n, static_cast<I &&>(bound));
0354 return it;
0355 }
0356 };
0357
0358
0359 RANGES_INLINE_VARIABLE(prev_fn, prev)
0360
0361 struct iter_enumerate_fn
0362 {
0363 private:
0364 template(typename I, typename S)(
0365 requires (!sized_sentinel_for<I, I>))
0366 static constexpr std::pair<iter_difference_t<I>, I>
0367 impl_i(I first, S last, sentinel_tag)
0368 {
0369 iter_difference_t<I> d = 0;
0370 for(; first != last; ++first)
0371 ++d;
0372 return {d, first};
0373 }
0374 template(typename I, typename S)(
0375 requires sized_sentinel_for<I, I>)
0376 static constexpr std::pair<iter_difference_t<I>, I>
0377 impl_i(I first, S end_, sentinel_tag)
0378 {
0379 I last = ranges::next(first, end_);
0380 auto n = static_cast<iter_difference_t<I>>(last - first);
0381 RANGES_EXPECT(((bool)same_as<I, S> || 0 <= n));
0382 return {n, last};
0383 }
0384 template<typename I, typename S>
0385 static constexpr std::pair<iter_difference_t<I>, I>
0386 impl_i(I first, S last, sized_sentinel_tag)
0387 {
0388 auto n = static_cast<iter_difference_t<I>>(last - first);
0389 RANGES_EXPECT(((bool)same_as<I, S> || 0 <= n));
0390 return {n, ranges::next(first, last)};
0391 }
0392
0393 public:
0394 template(typename I, typename S)(
0395 requires sentinel_for<S, I>)
0396 constexpr std::pair<iter_difference_t<I>, I> operator()(I first, S last) const
0397 {
0398 return iter_enumerate_fn::impl_i(static_cast<I &&>(first),
0399 static_cast<S &&>(last),
0400 sentinel_tag_of<S, I>());
0401 }
0402 };
0403
0404
0405 RANGES_INLINE_VARIABLE(iter_enumerate_fn, iter_enumerate)
0406
0407 struct iter_distance_fn
0408 {
0409 private:
0410 template<typename I, typename S>
0411 static constexpr iter_difference_t<I> impl_i(I first, S last, sentinel_tag)
0412 {
0413 return iter_enumerate(static_cast<I &&>(first), static_cast<S &&>(last))
0414 .first;
0415 }
0416 template<typename I, typename S>
0417 static constexpr iter_difference_t<I> impl_i(I first, S last, sized_sentinel_tag)
0418 {
0419 auto n = static_cast<iter_difference_t<I>>(last - first);
0420 RANGES_EXPECT(((bool)same_as<I, S> || 0 <= n));
0421 return n;
0422 }
0423
0424 public:
0425 template(typename I, typename S)(
0426 requires input_or_output_iterator<I> AND sentinel_for<S, I>)
0427 constexpr iter_difference_t<I> operator()(I first, S last) const
0428 {
0429 return iter_distance_fn::impl_i(static_cast<I &&>(first),
0430 static_cast<S &&>(last),
0431 sentinel_tag_of<S, I>());
0432 }
0433 };
0434
0435
0436 RANGES_INLINE_VARIABLE(iter_distance_fn, iter_distance)
0437
0438 struct iter_distance_compare_fn
0439 {
0440 private:
0441 template<typename I, typename S>
0442 static constexpr int impl_i(I first, S last, iter_difference_t<I> n, sentinel_tag)
0443 {
0444 if(n < 0)
0445 return 1;
0446 for(; n > 0; --n, ++first)
0447 {
0448 if(first == last)
0449 return -1;
0450 }
0451 return first == last ? 0 : 1;
0452 }
0453 template<typename I, typename S>
0454 static constexpr int impl_i(I first, S last, iter_difference_t<I> n,
0455 sized_sentinel_tag)
0456 {
0457 iter_difference_t<I> dist = last - first;
0458 if(n < dist)
0459 return 1;
0460 if(dist < n)
0461 return -1;
0462 return 0;
0463 }
0464
0465 public:
0466 template(typename I, typename S)(
0467 requires input_iterator<I> AND sentinel_for<S, I>)
0468 constexpr int operator()(I first, S last, iter_difference_t<I> n) const
0469 {
0470 return iter_distance_compare_fn::impl_i(static_cast<I &&>(first),
0471 static_cast<S &&>(last),
0472 n,
0473 sentinel_tag_of<S, I>());
0474 }
0475 };
0476
0477
0478 RANGES_INLINE_VARIABLE(iter_distance_compare_fn, iter_distance_compare)
0479
0480
0481 struct iter_size_fn
0482 {
0483 template(typename I, typename S)(
0484 requires sized_sentinel_for<S, I>)
0485 constexpr meta::_t<std::make_unsigned<iter_difference_t<I>>>
0486 operator()(I const & first, S last) const
0487 {
0488 using size_type = meta::_t<std::make_unsigned<iter_difference_t<I>>>;
0489 iter_difference_t<I> n = last - first;
0490 RANGES_EXPECT(0 <= n);
0491 return static_cast<size_type>(n);
0492 }
0493 };
0494
0495
0496 RANGES_INLINE_VARIABLE(iter_size_fn, iter_size)
0497
0498
0499 namespace adl_uncounted_recounted_detail
0500 {
0501 template<typename I>
0502 constexpr I uncounted(I i)
0503 {
0504 return i;
0505 }
0506
0507 template<typename I>
0508 constexpr I recounted(I const &, I i, iter_difference_t<I>)
0509 {
0510 return i;
0511 }
0512
0513 struct uncounted_fn
0514 {
0515 template<typename I>
0516 constexpr auto operator()(I i) const -> decltype(uncounted((I &&) i))
0517 {
0518 return uncounted((I &&) i);
0519 }
0520 };
0521
0522 struct recounted_fn
0523 {
0524 template<typename I, typename J>
0525 constexpr auto operator()(I i, J j, iter_difference_t<J> n) const
0526 -> decltype(recounted((I &&) i, (J &&) j, n))
0527 {
0528 return recounted((I &&) i, (J &&) j, n);
0529 }
0530 };
0531 }
0532
0533
0534 RANGES_INLINE_VARIABLE(adl_uncounted_recounted_detail::uncounted_fn, uncounted)
0535 RANGES_INLINE_VARIABLE(adl_uncounted_recounted_detail::recounted_fn, recounted)
0536
0537 struct enumerate_fn : iter_enumerate_fn
0538 {
0539 private:
0540 template<typename Rng>
0541 static constexpr std::pair<range_difference_t<Rng>, iterator_t<Rng>> impl_r(
0542 Rng & rng, range_tag, range_tag)
0543 {
0544 return iter_enumerate(begin(rng), end(rng));
0545 }
0546 template<typename Rng>
0547 static constexpr std::pair<range_difference_t<Rng>, iterator_t<Rng>> impl_r(
0548 Rng & rng, common_range_tag, sized_range_tag)
0549 {
0550 return {static_cast<range_difference_t<Rng>>(size(rng)), end(rng)};
0551 }
0552
0553 public:
0554 using iter_enumerate_fn::operator();
0555
0556 template(typename Rng)(
0557 requires range<Rng>)
0558 constexpr std::pair<range_difference_t<Rng>, iterator_t<Rng>> operator()(Rng && rng) const
0559 {
0560
0561 RANGES_EXPECT(!is_infinite<Rng>::value);
0562 return enumerate_fn::impl_r(
0563 rng, common_range_tag_of<Rng>(), sized_range_tag_of<Rng>());
0564 }
0565 };
0566
0567
0568 RANGES_INLINE_VARIABLE(enumerate_fn, enumerate)
0569
0570 struct distance_fn : iter_distance_fn
0571 {
0572 private:
0573 template<typename Rng>
0574 static range_difference_t<Rng> impl_r(Rng & rng, range_tag)
0575 {
0576 return enumerate(rng).first;
0577 }
0578 template<typename Rng>
0579 static constexpr range_difference_t<Rng> impl_r(Rng & rng, sized_range_tag)
0580 {
0581 return static_cast<range_difference_t<Rng>>(size(rng));
0582 }
0583
0584 public:
0585 using iter_distance_fn::operator();
0586
0587 template(typename Rng)(
0588 requires range<Rng>)
0589 constexpr range_difference_t<Rng> operator()(Rng && rng) const
0590 {
0591
0592 RANGES_EXPECT(!is_infinite<Rng>::value);
0593 return distance_fn::impl_r(rng, sized_range_tag_of<Rng>());
0594 }
0595 };
0596
0597
0598 RANGES_INLINE_VARIABLE(distance_fn, distance)
0599
0600
0601 struct distance_compare_fn : iter_distance_compare_fn
0602 {
0603 private:
0604 template<typename Rng>
0605 static constexpr int impl_r(Rng & rng, range_difference_t<Rng> n, range_tag)
0606 {
0607
0608 return is_infinite<Rng>::value
0609 ? 1
0610 : iter_distance_compare(begin(rng), end(rng), n);
0611 }
0612 template<typename Rng>
0613 static constexpr int impl_r(Rng & rng, range_difference_t<Rng> n, sized_range_tag)
0614 {
0615 auto dist = distance(rng);
0616 if(dist > n)
0617 return 1;
0618 else if(dist < n)
0619 return -1;
0620 else
0621 return 0;
0622 }
0623
0624 public:
0625 using iter_distance_compare_fn::operator();
0626
0627 template(typename Rng)(
0628 requires range<Rng>)
0629 constexpr int operator()(Rng && rng, range_difference_t<Rng> n) const
0630 {
0631 return distance_compare_fn::impl_r(rng, n, sized_range_tag_of<Rng>());
0632 }
0633 };
0634
0635
0636 RANGES_INLINE_VARIABLE(distance_compare_fn, distance_compare)
0637
0638 namespace cpp20
0639 {
0640 using ranges::advance;
0641 using ranges::distance;
0642 using ranges::next;
0643 using ranges::prev;
0644 }
0645
0646 }
0647
0648 #include <range/v3/detail/epilogue.hpp>
0649
0650 #endif