File indexing completed on 2025-01-18 10:09:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_ITERATOR_BASIC_ITERATOR_HPP
0015 #define RANGES_V3_ITERATOR_BASIC_ITERATOR_HPP
0016
0017 #include <type_traits>
0018 #include <utility>
0019
0020 #include <meta/meta.hpp>
0021
0022 #include <concepts/concepts.hpp>
0023
0024 #include <range/v3/range_fwd.hpp>
0025
0026 #include <range/v3/detail/range_access.hpp>
0027 #include <range/v3/iterator/concepts.hpp>
0028 #include <range/v3/iterator/traits.hpp>
0029 #include <range/v3/utility/addressof.hpp>
0030 #include <range/v3/utility/box.hpp>
0031 #include <range/v3/utility/move.hpp>
0032 #include <range/v3/utility/semiregular_box.hpp>
0033 #include <range/v3/utility/static_const.hpp>
0034
0035 #include <range/v3/detail/prologue.hpp>
0036
0037 RANGES_DIAGNOSTIC_PUSH
0038 RANGES_DIAGNOSTIC_IGNORE_MULTIPLE_ASSIGNMENT_OPERATORS
0039
0040 namespace ranges
0041 {
0042
0043
0044
0045 template<typename T>
0046 struct basic_mixin : private box<T>
0047 {
0048 CPP_member
0049 constexpr CPP_ctor(basic_mixin)()(
0050 noexcept(std::is_nothrow_default_constructible<T>::value)
0051 requires default_constructible<T>)
0052 : box<T>{}
0053 {}
0054 CPP_member
0055 constexpr explicit CPP_ctor(basic_mixin)(T && t)(
0056 noexcept(std::is_nothrow_move_constructible<T>::value)
0057 requires move_constructible<T>)
0058 : box<T>(detail::move(t))
0059 {}
0060 CPP_member
0061 constexpr explicit CPP_ctor(basic_mixin)(T const & t)(
0062 noexcept(std::is_nothrow_copy_constructible<T>::value)
0063 requires copy_constructible<T>)
0064 : box<T>(t)
0065 {}
0066
0067 protected:
0068 using box<T>::get;
0069 };
0070
0071
0072 namespace detail
0073 {
0074 template<typename Cur>
0075 using cursor_reference_t =
0076 decltype(range_access::read(std::declval<Cur const &>()));
0077
0078
0079 template<typename Cur>
0080 auto cursor_move(Cur const & cur, int) -> decltype(range_access::move(cur));
0081 template<typename Cur>
0082 auto cursor_move(Cur const & cur, long) -> aux::move_t<cursor_reference_t<Cur>>;
0083
0084 template<typename Cur>
0085 using cursor_rvalue_reference_t =
0086 decltype(detail::cursor_move(std::declval<Cur const &>(), 42));
0087
0088
0089
0090
0091 template<typename Derived, typename Head>
0092 struct proxy_reference_conversion
0093 {
0094 operator Head() const
0095 noexcept(noexcept(Head(Head(std::declval<Derived const &>().read_()))))
0096 {
0097 return Head(static_cast<Derived const *>(this)->read_());
0098 }
0099 };
0100
0101
0102 template<typename Cur, bool IsReadable>
0103 struct cursor_traits_
0104 {
0105 private:
0106 struct private_
0107 {};
0108
0109 public:
0110 using value_t_ = private_;
0111 using reference_t_ = private_;
0112 using rvalue_reference_t_ = private_;
0113 using common_refs = meta::list<>;
0114 };
0115
0116 template<typename Cur>
0117 struct cursor_traits_<Cur, true>
0118 {
0119 using value_t_ = range_access::cursor_value_t<Cur>;
0120 using reference_t_ = cursor_reference_t<Cur>;
0121 using rvalue_reference_t_ = cursor_rvalue_reference_t<Cur>;
0122
0123 private:
0124 using R1 = reference_t_;
0125 using R2 = common_reference_t<reference_t_, value_t_ &>;
0126 using R3 = common_reference_t<reference_t_, rvalue_reference_t_>;
0127 using tmp1 = meta::list<value_t_, R1>;
0128 using tmp2 =
0129 meta::if_<meta::in<tmp1, uncvref_t<R2>>, tmp1, meta::push_back<tmp1, R2>>;
0130 using tmp3 =
0131 meta::if_<meta::in<tmp2, uncvref_t<R3>>, tmp2, meta::push_back<tmp2, R3>>;
0132
0133 public:
0134 using common_refs = meta::unique<meta::pop_front<tmp3>>;
0135 };
0136
0137 template<typename Cur>
0138 using cursor_traits = cursor_traits_<Cur, (bool)readable_cursor<Cur>>;
0139
0140 template<typename Cur>
0141 using cursor_value_t = typename cursor_traits<Cur>::value_t_;
0142
0143 template<typename Cur, bool IsReadable>
0144 struct basic_proxy_reference_;
0145 template<typename Cur>
0146 using basic_proxy_reference =
0147 basic_proxy_reference_<Cur, (bool)readable_cursor<Cur>>;
0148
0149
0150
0151
0152 template<typename Cur, bool IsReadable >
0153 struct RANGES_EMPTY_BASES basic_proxy_reference_
0154 : cursor_traits<Cur>
0155
0156
0157 , meta::inherit<meta::transform<
0158 typename cursor_traits<Cur>::common_refs,
0159 meta::bind_front<meta::quote<proxy_reference_conversion>,
0160 basic_proxy_reference_<Cur, IsReadable>>>>
0161 {
0162 private:
0163 Cur * cur_;
0164 template<typename, bool>
0165 friend struct basic_proxy_reference_;
0166 template<typename, typename>
0167 friend struct proxy_reference_conversion;
0168 using typename cursor_traits<Cur>::value_t_;
0169 using typename cursor_traits<Cur>::reference_t_;
0170 using typename cursor_traits<Cur>::rvalue_reference_t_;
0171 static_assert((bool)common_reference_with<value_t_ &, reference_t_>,
0172 "Your readable and writable cursor must have a value type and "
0173 "a reference type that share a common reference type. See the "
0174 "ranges::common_reference type trait.");
0175
0176 public:
0177 constexpr reference_t_ read_() const noexcept(
0178 noexcept(reference_t_(range_access::read(std::declval<Cur const &>()))))
0179 {
0180 return range_access::read(*cur_);
0181 }
0182 template<typename T>
0183 constexpr void write_(T && t) const
0184 {
0185 range_access::write(*cur_, (T &&) t);
0186 }
0187
0188 basic_proxy_reference_() = default;
0189 basic_proxy_reference_(basic_proxy_reference_ const &) = default;
0190 template(typename OtherCur)(
0191 requires convertible_to<OtherCur *, Cur *>)
0192 constexpr basic_proxy_reference_(
0193 basic_proxy_reference<OtherCur> const & that) noexcept
0194 : cur_(that.cur_)
0195 {}
0196 constexpr explicit basic_proxy_reference_(Cur & cur) noexcept
0197 : cur_(&cur)
0198 {}
0199 CPP_member
0200 constexpr auto operator=(basic_proxy_reference_ && that)
0201 -> CPP_ret(basic_proxy_reference_ &)(
0202 requires readable_cursor<Cur>)
0203 {
0204 return *this = that;
0205 }
0206 CPP_member
0207 constexpr auto operator=(basic_proxy_reference_ const & that)
0208 -> CPP_ret(basic_proxy_reference_ &)(
0209 requires readable_cursor<Cur>)
0210 {
0211 this->write_(that.read_());
0212 return *this;
0213 }
0214 CPP_member
0215 constexpr auto operator=(basic_proxy_reference_ && that) const
0216 -> CPP_ret(basic_proxy_reference_ const &)(
0217 requires readable_cursor<Cur>)
0218 {
0219 return *this = that;
0220 }
0221 CPP_member
0222 constexpr auto operator=(basic_proxy_reference_ const & that) const
0223 -> CPP_ret(basic_proxy_reference_ const &)(
0224 requires readable_cursor<Cur>)
0225 {
0226 this->write_(that.read_());
0227 return *this;
0228 }
0229 template(typename OtherCur)(
0230 requires readable_cursor<OtherCur> AND
0231 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
0232 constexpr basic_proxy_reference_ &
0233 operator=(basic_proxy_reference<OtherCur> && that)
0234 {
0235 return *this = that;
0236 }
0237 template(typename OtherCur)(
0238 requires readable_cursor<OtherCur> AND
0239 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
0240 constexpr basic_proxy_reference_ &
0241 operator=(basic_proxy_reference<OtherCur> const & that)
0242 {
0243 this->write_(that.read_());
0244 return *this;
0245 }
0246 template(typename OtherCur)(
0247 requires readable_cursor<OtherCur> AND
0248 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
0249 constexpr basic_proxy_reference_ const &
0250 operator=(basic_proxy_reference<OtherCur> && that) const
0251 {
0252 return *this = that;
0253 }
0254 template(typename OtherCur)(
0255 requires readable_cursor<OtherCur> AND
0256 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
0257 constexpr basic_proxy_reference_ const &
0258 operator=(basic_proxy_reference<OtherCur> const & that) const
0259 {
0260 this->write_(that.read_());
0261 return *this;
0262 }
0263 template(typename T)(
0264 requires writable_cursor<Cur, T>)
0265 constexpr basic_proxy_reference_ & operator=(T && t)
0266 {
0267 this->write_((T &&) t);
0268 return *this;
0269 }
0270 template(typename T)(
0271 requires writable_cursor<Cur, T>)
0272 constexpr basic_proxy_reference_ const & operator=(T && t) const
0273 {
0274 this->write_((T &&) t);
0275 return *this;
0276 }
0277 };
0278
0279 template(typename Cur, bool IsReadable)(
0280 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0281 constexpr bool operator==(basic_proxy_reference_<Cur, IsReadable> const & x,
0282 cursor_value_t<Cur> const & y)
0283 {
0284 return x.read_() == y;
0285 }
0286 template(typename Cur, bool IsReadable)(
0287 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0288 constexpr bool operator!=(basic_proxy_reference_<Cur, IsReadable> const & x,
0289 cursor_value_t<Cur> const & y)
0290 {
0291 return !(x == y);
0292 }
0293 template(typename Cur, bool IsReadable)(
0294 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0295 constexpr bool operator==(cursor_value_t<Cur> const & x,
0296 basic_proxy_reference_<Cur, IsReadable> const & y)
0297 {
0298 return x == y.read_();
0299 }
0300 template(typename Cur, bool IsReadable)(
0301 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0302 constexpr bool operator!=(cursor_value_t<Cur> const & x,
0303 basic_proxy_reference_<Cur, IsReadable> const & y)
0304 {
0305 return !(x == y);
0306 }
0307 template(typename Cur, bool IsReadable)(
0308 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0309 constexpr bool operator==(basic_proxy_reference_<Cur, IsReadable> const & x,
0310 basic_proxy_reference_<Cur, IsReadable> const & y)
0311 {
0312 return x.read_() == y.read_();
0313 }
0314 template(typename Cur, bool IsReadable)(
0315 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
0316 constexpr bool operator!=(basic_proxy_reference_<Cur, IsReadable> const & x,
0317 basic_proxy_reference_<Cur, IsReadable> const & y)
0318 {
0319 return !(x == y);
0320 }
0321
0322 template<typename Cur>
0323 using cpp20_iter_cat_of_t =
0324 std::enable_if_t<
0325 input_cursor<Cur>,
0326 meta::conditional_t<
0327 contiguous_cursor<Cur>,
0328 ranges::contiguous_iterator_tag,
0329 meta::conditional_t<
0330 random_access_cursor<Cur>,
0331 std::random_access_iterator_tag,
0332 meta::conditional_t<
0333 bidirectional_cursor<Cur>,
0334 std::bidirectional_iterator_tag,
0335 meta::conditional_t<
0336 forward_cursor<Cur>,
0337 std::forward_iterator_tag,
0338 std::input_iterator_tag>>>>>;
0339
0340
0341
0342
0343 template(typename C)(
0344 concept (cpp17_input_cursor_)(C),
0345
0346
0347 !range_access::single_pass_t<uncvref_t<C>>::value ||
0348 (move_constructible<range_access::cursor_value_t<C>> &&
0349 constructible_from<range_access::cursor_value_t<C>, cursor_reference_t<C>>)
0350 );
0351
0352
0353
0354 template<typename C>
0355 CPP_concept cpp17_input_cursor =
0356 input_cursor<C> &&
0357 sentinel_for_cursor<C, C> &&
0358 CPP_concept_ref(cpp17_input_cursor_, C);
0359
0360
0361
0362 template(typename C)(
0363 concept (cpp17_forward_cursor_)(C),
0364 std::is_reference<cursor_reference_t<C>>::value
0365 );
0366
0367
0368
0369 template<typename C>
0370 CPP_concept cpp17_forward_cursor =
0371 forward_cursor<C> &&
0372 CPP_concept_ref(cpp17_forward_cursor_, C);
0373
0374
0375 template<typename Category, typename Base = void>
0376 struct with_iterator_category : Base
0377 {
0378 using iterator_category = Category;
0379 };
0380
0381 template<typename Category>
0382 struct with_iterator_category<Category>
0383 {
0384 using iterator_category = Category;
0385 };
0386
0387 template<typename Cur>
0388 using cpp17_iter_cat_of_t =
0389 std::enable_if_t<
0390 cpp17_input_cursor<Cur>,
0391 meta::conditional_t<
0392 random_access_cursor<Cur>,
0393 std::random_access_iterator_tag,
0394 meta::conditional_t<
0395 bidirectional_cursor<Cur>,
0396 std::bidirectional_iterator_tag,
0397 meta::conditional_t<
0398 cpp17_forward_cursor<Cur>,
0399 std::forward_iterator_tag,
0400 std::input_iterator_tag>>>>;
0401
0402 template<typename Cur, typename = void>
0403 struct readable_iterator_associated_types_base : range_access::mixin_base_t<Cur>
0404 {
0405 readable_iterator_associated_types_base() = default;
0406 using range_access::mixin_base_t<Cur>::mixin_base_t;
0407 readable_iterator_associated_types_base(Cur && cur)
0408 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
0409 {}
0410 readable_iterator_associated_types_base(Cur const & cur)
0411 : range_access::mixin_base_t<Cur>(cur)
0412 {}
0413 };
0414
0415 template<typename Cur>
0416 struct readable_iterator_associated_types_base<
0417 Cur, always_<void, cpp17_iter_cat_of_t<Cur>>>
0418 : range_access::mixin_base_t<Cur>
0419 {
0420 using iterator_category = cpp17_iter_cat_of_t<Cur>;
0421 readable_iterator_associated_types_base() = default;
0422 using range_access::mixin_base_t<Cur>::mixin_base_t;
0423 readable_iterator_associated_types_base(Cur && cur)
0424 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
0425 {}
0426 readable_iterator_associated_types_base(Cur const & cur)
0427 : range_access::mixin_base_t<Cur>(cur)
0428 {}
0429 };
0430
0431 template<typename Cur, bool IsReadable >
0432 struct iterator_associated_types_base_ : range_access::mixin_base_t<Cur>
0433 {
0434
0435
0436 using iter_reference_t = basic_proxy_reference<Cur>;
0437 using const_reference_t = basic_proxy_reference<Cur const>;
0438
0439 public:
0440 using reference = void;
0441 using difference_type = range_access::cursor_difference_t<Cur>;
0442
0443 iterator_associated_types_base_() = default;
0444 using range_access::mixin_base_t<Cur>::mixin_base_t;
0445 iterator_associated_types_base_(Cur && cur)
0446 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
0447 {}
0448 iterator_associated_types_base_(Cur const & cur)
0449 : range_access::mixin_base_t<Cur>(cur)
0450 {}
0451 };
0452
0453 template<typename Cur>
0454 using cursor_arrow_t = decltype(range_access::arrow(std::declval<Cur const &>()));
0455
0456 template<typename Cur>
0457 struct iterator_associated_types_base_<Cur, true>
0458 : readable_iterator_associated_types_base<Cur>
0459 {
0460
0461
0462 using iter_reference_t =
0463 meta::conditional_t<is_writable_cursor_v<Cur const>,
0464 basic_proxy_reference<Cur const>,
0465 meta::conditional_t<is_writable_cursor_v<Cur>,
0466 basic_proxy_reference<Cur>, cursor_reference_t<Cur>>>;
0467 using const_reference_t =
0468 meta::conditional_t<is_writable_cursor_v<Cur const>,
0469 basic_proxy_reference<Cur const>, cursor_reference_t<Cur>>;
0470
0471 public:
0472 using difference_type = range_access::cursor_difference_t<Cur>;
0473 using value_type = range_access::cursor_value_t<Cur>;
0474 using reference = iter_reference_t;
0475 using iterator_concept = cpp20_iter_cat_of_t<Cur>;
0476 using pointer = meta::_t<
0477 meta::conditional_t<
0478 (bool)has_cursor_arrow<Cur>,
0479 meta::defer<cursor_arrow_t, Cur>,
0480 std::add_pointer<reference>>>;
0481 using common_reference = common_reference_t<reference, value_type &>;
0482
0483 iterator_associated_types_base_() = default;
0484 using readable_iterator_associated_types_base<
0485 Cur>::readable_iterator_associated_types_base;
0486 iterator_associated_types_base_(Cur && cur)
0487 : readable_iterator_associated_types_base<Cur>(static_cast<Cur &&>(cur))
0488 {}
0489 iterator_associated_types_base_(Cur const & cur)
0490 : readable_iterator_associated_types_base<Cur>(cur)
0491 {}
0492 };
0493
0494 template<typename Cur>
0495 using iterator_associated_types_base =
0496 iterator_associated_types_base_<Cur, (bool)readable_cursor<Cur>>;
0497
0498 template<typename Value>
0499 struct postfix_increment_proxy
0500 {
0501 private:
0502 Value cache_;
0503
0504 public:
0505 template<typename T>
0506 constexpr postfix_increment_proxy(T && t)
0507 : cache_(static_cast<T &&>(t))
0508 {}
0509 constexpr Value const & operator*() const noexcept
0510 {
0511 return cache_;
0512 }
0513 };
0514 }
0515
0516
0517 #if RANGES_BROKEN_CPO_LOOKUP
0518 namespace _basic_iterator_
0519 {
0520 template<typename>
0521 struct adl_hook
0522 {};
0523 }
0524 #endif
0525
0526 template<typename Cur>
0527 struct RANGES_EMPTY_BASES basic_iterator
0528 : detail::iterator_associated_types_base<Cur>
0529 #if RANGES_BROKEN_CPO_LOOKUP
0530 , private _basic_iterator_::adl_hook<basic_iterator<Cur>>
0531 #endif
0532 {
0533 private:
0534 template<typename>
0535 friend struct basic_iterator;
0536 friend range_access;
0537 using base_t = detail::iterator_associated_types_base<Cur>;
0538 using mixin_t = range_access::mixin_base_t<Cur>;
0539 static_assert((bool)detail::cursor<Cur>, "");
0540 using assoc_types_ = detail::iterator_associated_types_base<Cur>;
0541 using typename assoc_types_::const_reference_t;
0542 using typename assoc_types_::iter_reference_t;
0543 constexpr Cur & pos() noexcept
0544 {
0545 return this->mixin_t::basic_mixin::get();
0546 }
0547 constexpr Cur const & pos() const noexcept
0548 {
0549 return this->mixin_t::basic_mixin::get();
0550 }
0551
0552 public:
0553 using typename assoc_types_::difference_type;
0554 constexpr basic_iterator() = default;
0555 template(typename OtherCur)(
0556 requires (!same_as<OtherCur, Cur>) AND convertible_to<OtherCur, Cur> AND
0557 constructible_from<mixin_t, OtherCur>)
0558 constexpr basic_iterator(basic_iterator<OtherCur> that)
0559 : base_t{std::move(that.pos())}
0560 {}
0561
0562 using base_t::base_t;
0563
0564 explicit basic_iterator(Cur && cur)
0565 : base_t(static_cast<Cur &&>(cur))
0566 {}
0567
0568 explicit basic_iterator(Cur const & cur)
0569 : base_t(cur)
0570 {}
0571
0572 template(typename OtherCur)(
0573 requires (!same_as<OtherCur, Cur>) AND convertible_to<OtherCur, Cur>)
0574 constexpr basic_iterator & operator=(basic_iterator<OtherCur> that)
0575 {
0576 pos() = std::move(that.pos());
0577 return *this;
0578 }
0579
0580 CPP_member
0581 constexpr auto operator*() const
0582 noexcept(noexcept(range_access::read(std::declval<Cur const &>())))
0583 -> CPP_ret(const_reference_t)(
0584 requires detail::readable_cursor<Cur> &&
0585 (!detail::is_writable_cursor_v<Cur>))
0586 {
0587 return range_access::read(pos());
0588 }
0589 CPP_member
0590 constexpr auto operator*()
0591 noexcept(noexcept(iter_reference_t{std::declval<Cur &>()}))
0592 -> CPP_ret(iter_reference_t)(
0593 requires detail::has_cursor_next<Cur> &&
0594 detail::is_writable_cursor_v<Cur>)
0595 {
0596 return iter_reference_t{pos()};
0597 }
0598 CPP_member
0599 constexpr auto operator*() const
0600 noexcept(noexcept(const_reference_t{std::declval<Cur const &>()}))
0601 -> CPP_ret(const_reference_t)(
0602 requires detail::has_cursor_next<Cur> &&
0603 detail::is_writable_cursor_v<Cur const>)
0604 {
0605 return const_reference_t{pos()};
0606 }
0607 CPP_member
0608 constexpr auto operator*() noexcept
0609 -> CPP_ret(basic_iterator &)(
0610 requires (!detail::has_cursor_next<Cur>))
0611 {
0612 return *this;
0613 }
0614
0615
0616 template(typename C = Cur)(
0617 requires detail::has_cursor_arrow<C>)
0618 constexpr detail::cursor_arrow_t<C> operator-> () const
0619 noexcept(noexcept(range_access::arrow(std::declval<C const &>())))
0620 {
0621 return range_access::arrow(pos());
0622 }
0623
0624
0625 template(typename C = Cur)(
0626 requires (!detail::has_cursor_arrow<C>) AND detail::readable_cursor<C> AND
0627 std::is_lvalue_reference<const_reference_t>::value AND
0628 same_as<typename detail::iterator_associated_types_base<C>::value_type,
0629 uncvref_t<const_reference_t>>)
0630 constexpr std::add_pointer_t<const_reference_t> operator-> () const
0631 noexcept(noexcept(*std::declval<basic_iterator const &>()))
0632 {
0633 return detail::addressof(**this);
0634 }
0635
0636 CPP_member
0637 constexpr auto operator++()
0638 -> CPP_ret(basic_iterator &)(
0639 requires detail::has_cursor_next<Cur>)
0640 {
0641 range_access::next(pos());
0642 return *this;
0643 }
0644 CPP_member
0645 constexpr auto operator++() noexcept
0646 -> CPP_ret(basic_iterator &)(
0647 requires (!detail::has_cursor_next<Cur>))
0648 {
0649 return *this;
0650 }
0651
0652 private:
0653 constexpr basic_iterator post_increment_(std::false_type, int)
0654 {
0655 basic_iterator tmp{*this};
0656 ++*this;
0657 return tmp;
0658 }
0659
0660
0661 template(typename A = assoc_types_, typename V = typename A::value_type)(
0662 requires constructible_from<V, typename A::reference> AND
0663 move_constructible<V>)
0664 constexpr auto post_increment_(std::true_type, int)
0665 -> detail::postfix_increment_proxy<V>
0666 {
0667 detail::postfix_increment_proxy<V> p{**this};
0668 ++*this;
0669 return p;
0670 }
0671 constexpr void post_increment_(std::true_type, long)
0672 {
0673 ++*this;
0674 }
0675
0676 public:
0677 CPP_member
0678 constexpr auto operator++(int)
0679 {
0680 return this->post_increment_(meta::bool_ < detail::input_cursor<Cur> &&
0681 !detail::forward_cursor<Cur>> {},
0682 0);
0683 }
0684
0685 CPP_member
0686 constexpr auto operator--()
0687 -> CPP_ret(basic_iterator &)(
0688 requires detail::bidirectional_cursor<Cur>)
0689 {
0690 range_access::prev(pos());
0691 return *this;
0692 }
0693 CPP_member
0694 constexpr auto operator--(int)
0695 -> CPP_ret(basic_iterator)(
0696 requires detail::bidirectional_cursor<Cur>)
0697 {
0698 basic_iterator tmp(*this);
0699 --*this;
0700 return tmp;
0701 }
0702 CPP_member
0703 constexpr auto operator+=(difference_type n)
0704 -> CPP_ret(basic_iterator &)(
0705 requires detail::random_access_cursor<Cur>)
0706 {
0707 range_access::advance(pos(), n);
0708 return *this;
0709 }
0710 CPP_member
0711 constexpr auto operator-=(difference_type n)
0712 -> CPP_ret(basic_iterator &)(
0713 requires detail::random_access_cursor<Cur>)
0714 {
0715 range_access::advance(pos(), (difference_type)-n);
0716 return *this;
0717 }
0718 CPP_member
0719 constexpr auto operator[](difference_type n) const
0720 -> CPP_ret(const_reference_t)(
0721 requires detail::random_access_cursor<Cur>)
0722 {
0723 return *(*this + n);
0724 }
0725
0726 #if !RANGES_BROKEN_CPO_LOOKUP
0727
0728
0729 template<typename C = Cur>
0730 friend constexpr auto iter_move(basic_iterator const & it) noexcept(
0731 noexcept(range_access::move(std::declval<C const &>())))
0732 -> CPP_broken_friend_ret(
0733 decltype(range_access::move(std::declval<C const &>())))(
0734 requires same_as<C, Cur> && detail::input_cursor<Cur>)
0735 {
0736 return range_access::move(it.pos());
0737 }
0738 #endif
0739 };
0740
0741 template(typename Cur, typename Cur2)(
0742 requires detail::sentinel_for_cursor<Cur2, Cur>)
0743 constexpr bool operator==(basic_iterator<Cur> const & left,
0744 basic_iterator<Cur2> const & right)
0745 {
0746 return range_access::equal(range_access::pos(left), range_access::pos(right));
0747 }
0748 template(typename Cur, typename Cur2)(
0749 requires detail::sentinel_for_cursor<Cur2, Cur>)
0750 constexpr bool operator!=(basic_iterator<Cur> const & left,
0751 basic_iterator<Cur2> const & right)
0752 {
0753 return !(left == right);
0754 }
0755 template(typename Cur, typename S)(
0756 requires detail::sentinel_for_cursor<S, Cur>)
0757 constexpr bool operator==(basic_iterator<Cur> const & left,
0758 S const & right)
0759 {
0760 return range_access::equal(range_access::pos(left), right);
0761 }
0762 template(typename Cur, typename S)(
0763 requires detail::sentinel_for_cursor<S, Cur>)
0764 constexpr bool operator!=(basic_iterator<Cur> const & left,
0765 S const & right)
0766 {
0767 return !(left == right);
0768 }
0769 template(typename S, typename Cur)(
0770 requires detail::sentinel_for_cursor<S, Cur>)
0771 constexpr bool operator==(S const & left,
0772 basic_iterator<Cur> const & right)
0773 {
0774 return right == left;
0775 }
0776 template(typename S, typename Cur)(
0777 requires detail::sentinel_for_cursor<S, Cur>)
0778 constexpr bool operator!=(S const & left,
0779 basic_iterator<Cur> const & right)
0780 {
0781 return right != left;
0782 }
0783
0784 template(typename Cur)(
0785 requires detail::random_access_cursor<Cur>)
0786 constexpr basic_iterator<Cur>
0787 operator+(basic_iterator<Cur> left, typename basic_iterator<Cur>::difference_type n)
0788 {
0789 left += n;
0790 return left;
0791 }
0792 template(typename Cur)(
0793 requires detail::random_access_cursor<Cur>)
0794 constexpr basic_iterator<Cur>
0795 operator+(typename basic_iterator<Cur>::difference_type n, basic_iterator<Cur> right)
0796 {
0797 right += n;
0798 return right;
0799 }
0800 template(typename Cur)(
0801 requires detail::random_access_cursor<Cur>)
0802 constexpr basic_iterator<Cur>
0803 operator-(basic_iterator<Cur> left, typename basic_iterator<Cur>::difference_type n)
0804 {
0805 left -= n;
0806 return left;
0807 }
0808 template(typename Cur2, typename Cur)(
0809 requires detail::sized_sentinel_for_cursor<Cur2, Cur>)
0810 constexpr typename basic_iterator<Cur>::difference_type
0811 operator-(basic_iterator<Cur2> const & left, basic_iterator<Cur> const & right)
0812 {
0813 return range_access::distance_to(range_access::pos(right),
0814 range_access::pos(left));
0815 }
0816 template(typename S, typename Cur)(
0817 requires detail::sized_sentinel_for_cursor<S, Cur>)
0818 constexpr typename basic_iterator<Cur>::difference_type
0819 operator-(S const & left, basic_iterator<Cur> const & right)
0820 {
0821 return range_access::distance_to(range_access::pos(right), left);
0822 }
0823 template(typename Cur, typename S)(
0824 requires detail::sized_sentinel_for_cursor<S, Cur>)
0825 constexpr typename basic_iterator<Cur>::difference_type
0826 operator-(basic_iterator<Cur> const & left, S const & right)
0827 {
0828 return -(right - left);
0829 }
0830
0831 template(typename Left, typename Right)(
0832 requires detail::sized_sentinel_for_cursor<Right, Left>)
0833 constexpr bool operator<(basic_iterator<Left> const & left,
0834 basic_iterator<Right> const & right)
0835 {
0836 return 0 < (right - left);
0837 }
0838 template(typename Left, typename Right)(
0839 requires detail::sized_sentinel_for_cursor<Right, Left>)
0840 constexpr bool operator<=(basic_iterator<Left> const & left,
0841 basic_iterator<Right> const & right)
0842 {
0843 return 0 <= (right - left);
0844 }
0845 template(typename Left, typename Right)(
0846 requires detail::sized_sentinel_for_cursor<Right, Left>)
0847 constexpr bool operator>(basic_iterator<Left> const & left,
0848 basic_iterator<Right> const & right)
0849 {
0850 return (right - left) < 0;
0851 }
0852 template(typename Left, typename Right)(
0853 requires detail::sized_sentinel_for_cursor<Right, Left>)
0854 constexpr bool operator>=(basic_iterator<Left> const & left,
0855 basic_iterator<Right> const & right)
0856 {
0857 return (right - left) <= 0;
0858 }
0859
0860 #if RANGES_BROKEN_CPO_LOOKUP
0861 namespace _basic_iterator_
0862 {
0863
0864
0865 template<typename Cur>
0866 constexpr auto iter_move(basic_iterator<Cur> const & it) noexcept(
0867 noexcept(range_access::move(std::declval<Cur const &>())))
0868 -> CPP_broken_friend_ret(
0869 decltype(range_access::move(std::declval<Cur const &>())))(
0870 requires detail::input_cursor<Cur>)
0871 {
0872 return range_access::move(range_access::pos(it));
0873 }
0874 }
0875 #endif
0876
0877
0878 struct get_cursor_fn
0879 {
0880 template<typename Cur>
0881 constexpr Cur & operator()(basic_iterator<Cur> & it) const noexcept
0882 {
0883 return range_access::pos(it);
0884 }
0885 template<typename Cur>
0886 constexpr Cur const & operator()(basic_iterator<Cur> const & it) const noexcept
0887 {
0888 return range_access::pos(it);
0889 }
0890 template<typename Cur>
0891 constexpr Cur operator()(basic_iterator<Cur> && it) const
0892 noexcept(std::is_nothrow_move_constructible<Cur>::value)
0893 {
0894 return range_access::pos(std::move(it));
0895 }
0896 };
0897
0898
0899 RANGES_INLINE_VARIABLE(get_cursor_fn, get_cursor)
0900
0901 }
0902
0903
0904 namespace concepts
0905 {
0906
0907 template<typename Cur, typename U, template<typename> class TQual,
0908 template<typename> class UQual>
0909 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur, true>, U,
0910 TQual, UQual>
0911 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur>, U, TQual, UQual>
0912 {};
0913 template<typename T, typename Cur, template<typename> class TQual,
0914 template<typename> class UQual>
0915 struct basic_common_reference<T, ::ranges::detail::basic_proxy_reference_<Cur, true>,
0916 TQual, UQual>
0917 : basic_common_reference<T, ::ranges::detail::cursor_reference_t<Cur>, TQual, UQual>
0918 {};
0919 template<typename Cur1, typename Cur2, template<typename> class TQual,
0920 template<typename> class UQual>
0921 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur1, true>,
0922 ::ranges::detail::basic_proxy_reference_<Cur2, true>,
0923 TQual, UQual>
0924 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur1>,
0925 ::ranges::detail::cursor_reference_t<Cur2>, TQual, UQual>
0926 {};
0927
0928
0929 template<typename Cur, typename U>
0930 struct common_type<::ranges::detail::basic_proxy_reference_<Cur, true>, U>
0931 : common_type<::ranges::range_access::cursor_value_t<Cur>, U>
0932 {};
0933 template<typename T, typename Cur>
0934 struct common_type<T, ::ranges::detail::basic_proxy_reference_<Cur, true>>
0935 : common_type<T, ::ranges::range_access::cursor_value_t<Cur>>
0936 {};
0937 template<typename Cur1, typename Cur2>
0938 struct common_type<::ranges::detail::basic_proxy_reference_<Cur1, true>,
0939 ::ranges::detail::basic_proxy_reference_<Cur2, true>>
0940 : common_type<::ranges::range_access::cursor_value_t<Cur1>,
0941 ::ranges::range_access::cursor_value_t<Cur2>>
0942 {};
0943 }
0944
0945 #if RANGES_CXX_VER > RANGES_CXX_STD_17
0946 RANGES_DIAGNOSTIC_PUSH
0947 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0948 RANGES_BEGIN_NAMESPACE_STD
0949 RANGES_BEGIN_NAMESPACE_VERSION
0950 template<typename, typename, template <typename> class, template<typename> class>
0951 struct basic_common_reference;
0952
0953
0954 template<typename Cur, typename U, template<typename> class TQual,
0955 template<typename> class UQual>
0956 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur, true>, U,
0957 TQual, UQual>
0958 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur>, U, TQual, UQual>
0959 {};
0960 template<typename T, typename Cur, template<typename> class TQual,
0961 template<typename> class UQual>
0962 struct basic_common_reference<T, ::ranges::detail::basic_proxy_reference_<Cur, true>,
0963 TQual, UQual>
0964 : basic_common_reference<T, ::ranges::detail::cursor_reference_t<Cur>, TQual, UQual>
0965 {};
0966 template<typename Cur1, typename Cur2, template<typename> class TQual,
0967 template<typename> class UQual>
0968 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur1, true>,
0969 ::ranges::detail::basic_proxy_reference_<Cur2, true>,
0970 TQual, UQual>
0971 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur1>,
0972 ::ranges::detail::cursor_reference_t<Cur2>, TQual, UQual>
0973 {};
0974
0975 template<typename...>
0976 struct common_type;
0977
0978
0979 template<typename Cur, typename U>
0980 struct common_type<::ranges::detail::basic_proxy_reference_<Cur, true>, U>
0981 : common_type<::ranges::range_access::cursor_value_t<Cur>, U>
0982 {};
0983 template<typename T, typename Cur>
0984 struct common_type<T, ::ranges::detail::basic_proxy_reference_<Cur, true>>
0985 : common_type<T, ::ranges::range_access::cursor_value_t<Cur>>
0986 {};
0987 template<typename Cur1, typename Cur2>
0988 struct common_type<::ranges::detail::basic_proxy_reference_<Cur1, true>,
0989 ::ranges::detail::basic_proxy_reference_<Cur2, true>>
0990 : common_type<::ranges::range_access::cursor_value_t<Cur1>,
0991 ::ranges::range_access::cursor_value_t<Cur2>>
0992 {};
0993 RANGES_END_NAMESPACE_VERSION
0994 RANGES_END_NAMESPACE_STD
0995 RANGES_DIAGNOSTIC_POP
0996 #endif
0997
0998 namespace ranges
0999 {
1000
1001 namespace detail
1002 {
1003 template<typename Cur, bool IsReadable>
1004 struct std_iterator_traits_
1005 {
1006 using difference_type =
1007 typename iterator_associated_types_base<Cur>::difference_type;
1008 using value_type = void;
1009 using reference = void;
1010 using pointer = void;
1011 using iterator_category = std::output_iterator_tag;
1012 using iterator_concept = std::output_iterator_tag;
1013 };
1014
1015 template<typename Cur>
1016 struct std_iterator_traits_<Cur, true> : iterator_associated_types_base<Cur>
1017 {};
1018
1019 template<typename Cur>
1020 using std_iterator_traits = std_iterator_traits_<Cur, (bool)readable_cursor<Cur>>;
1021 }
1022
1023 }
1024
1025 namespace std
1026 {
1027 template<typename Cur>
1028 struct iterator_traits<::ranges::basic_iterator<Cur>>
1029 : ::ranges::detail::std_iterator_traits<Cur>
1030 {};
1031 }
1032
1033
1034 RANGES_DIAGNOSTIC_POP
1035
1036 #include <range/v3/detail/epilogue.hpp>
1037
1038 #endif