File indexing completed on 2024-11-15 09:32:18
0001
0002
0003
0004
0005
0006 #ifndef BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP
0007 #define BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP
0008
0009 #include <boost/stl_interfaces/fwd.hpp>
0010
0011 #include <utility>
0012 #include <type_traits>
0013 #if defined(__cpp_lib_three_way_comparison)
0014 #include <compare>
0015 #endif
0016
0017
0018 namespace boost { namespace stl_interfaces {
0019
0020
0021
0022 struct access
0023 {
0024 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0025
0026 template<typename D>
0027 static constexpr auto base(D & d) noexcept
0028 -> decltype(d.base_reference())
0029 {
0030 return d.base_reference();
0031 }
0032 template<typename D>
0033 static constexpr auto base(D const & d) noexcept
0034 -> decltype(d.base_reference())
0035 {
0036 return d.base_reference();
0037 }
0038
0039 #endif
0040 };
0041
0042
0043
0044
0045
0046
0047
0048 template<typename T>
0049 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
0050
0051 requires std::is_object_v<T>
0052 #endif
0053 struct proxy_arrow_result
0054
0055 {
0056 constexpr proxy_arrow_result(T const & value) noexcept(
0057 noexcept(T(value))) :
0058 value_(value)
0059 {}
0060 constexpr proxy_arrow_result(T && value) noexcept(
0061 noexcept(T(std::move(value)))) :
0062 value_(std::move(value))
0063 {}
0064
0065 constexpr T const * operator->() const noexcept { return &value_; }
0066 constexpr T * operator->() noexcept { return &value_; }
0067
0068 private:
0069 T value_;
0070 };
0071
0072 namespace detail {
0073 template<typename Pointer, typename Reference, typename T>
0074 auto make_pointer(
0075 T && value,
0076 std::enable_if_t<
0077 std::is_pointer<Pointer>::value &&
0078 std::is_reference<Reference>::value,
0079 int> = 0) -> decltype(std::addressof(value))
0080 {
0081 return std::addressof(value);
0082 }
0083
0084 template<typename Pointer, typename Reference, typename T>
0085 auto make_pointer(
0086 T && value,
0087 std::enable_if_t<
0088 !std::is_pointer<Pointer>::value &&
0089 !std::is_same<Pointer, void>::value &&
0090 std::is_reference<Reference>::value,
0091 int> = 0)
0092 {
0093 return Pointer(std::forward<T>(value));
0094 }
0095
0096 template<typename Pointer, typename IteratorConcept>
0097 struct pointer
0098 {
0099 using type = Pointer;
0100 };
0101 template<typename Pointer>
0102 struct pointer<Pointer, std::output_iterator_tag>
0103 {
0104 using type = void;
0105 };
0106 template<typename Pointer, typename IteratorConcept>
0107 using pointer_t = typename pointer<Pointer, IteratorConcept>::type;
0108
0109 template<typename T, typename U>
0110 using interoperable = std::integral_constant<
0111 bool,
0112 (std::is_convertible<T, U>::value ||
0113 std::is_convertible<U, T>::value)>;
0114
0115 template<typename T, typename U>
0116 using common_t =
0117 std::conditional_t<std::is_convertible<T, U>::value, U, T>;
0118
0119 template<typename T>
0120 using use_base = decltype(access::base(std::declval<T &>()));
0121
0122 template<typename... T>
0123 using void_t = void;
0124
0125 template<
0126 typename AlwaysVoid,
0127 template<class...> class Template,
0128 typename... Args>
0129 struct detector : std::false_type
0130 {
0131 };
0132
0133 template<template<class...> class Template, typename... Args>
0134 struct detector<void_t<Template<Args...>>, Template, Args...>
0135 : std::true_type
0136 {
0137 };
0138
0139 template<
0140 typename T,
0141 typename U,
0142 bool UseBase = detector<void, use_base, T>::value>
0143 struct common_eq
0144 {
0145 static constexpr auto call(T lhs, U rhs)
0146 {
0147 return static_cast<common_t<T, U>>(lhs).derived() ==
0148 static_cast<common_t<T, U>>(rhs).derived();
0149 }
0150 };
0151 template<typename T, typename U>
0152 struct common_eq<T, U, true>
0153 {
0154 static constexpr auto call(T lhs, U rhs)
0155 {
0156 return access::base(lhs) == access::base(rhs);
0157 }
0158 };
0159
0160 template<typename T, typename U>
0161 constexpr auto common_diff(T lhs, U rhs) noexcept(noexcept(
0162 static_cast<common_t<T, U>>(lhs) -
0163 static_cast<common_t<T, U>>(rhs)))
0164 -> decltype(
0165 static_cast<common_t<T, U>>(lhs) -
0166 static_cast<common_t<T, U>>(rhs))
0167 {
0168 return static_cast<common_t<T, U>>(lhs) -
0169 static_cast<common_t<T, U>>(rhs);
0170 }
0171 }
0172
0173 }}
0174
0175 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 template<
0186 typename Derived,
0187 typename IteratorConcept,
0188 typename ValueType,
0189 typename Reference = ValueType &,
0190 typename Pointer = ValueType *,
0191 typename DifferenceType = std::ptrdiff_t
0192 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0193 ,
0194 typename E = std::enable_if_t<
0195 std::is_class<Derived>::value &&
0196 std::is_same<Derived, std::remove_cv_t<Derived>>::value>
0197 #endif
0198 >
0199 struct iterator_interface;
0200
0201 namespace v1_dtl {
0202 template<typename Iterator, typename = void>
0203 struct ra_iter : std::false_type
0204 {
0205 };
0206 template<typename Iterator>
0207 struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>>
0208 : std::integral_constant<
0209 bool,
0210 std::is_base_of<
0211 std::random_access_iterator_tag,
0212 typename Iterator::iterator_concept>::value>
0213 {
0214 };
0215
0216 template<typename Iterator, typename DifferenceType, typename = void>
0217 struct plus_eq : std::false_type
0218 {
0219 };
0220 template<typename Iterator, typename DifferenceType>
0221 struct plus_eq<
0222 Iterator,
0223 DifferenceType,
0224 void_t<decltype(
0225 std::declval<Iterator &>() += std::declval<DifferenceType>())>>
0226 : std::true_type
0227 {
0228 };
0229
0230 template<
0231 typename D,
0232 typename IteratorConcept,
0233 typename ValueType,
0234 typename Reference,
0235 typename Pointer,
0236 typename DifferenceType>
0237 void derived_iterator(iterator_interface<
0238 D,
0239 IteratorConcept,
0240 ValueType,
0241 Reference,
0242 Pointer,
0243 DifferenceType> const &);
0244 }
0245
0246 template<
0247 typename Derived,
0248 typename IteratorConcept,
0249 typename ValueType,
0250 typename Reference,
0251 typename Pointer,
0252 typename DifferenceType
0253 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0254 ,
0255 typename E
0256 #endif
0257 >
0258 struct iterator_interface
0259 {
0260 #ifndef BOOST_STL_INTERFACES_DOXYGEN
0261 private:
0262 constexpr Derived & derived() noexcept
0263 {
0264 return static_cast<Derived &>(*this);
0265 }
0266 constexpr Derived const & derived() const noexcept
0267 {
0268 return static_cast<Derived const &>(*this);
0269 }
0270
0271 template<typename T, typename U, bool UseBase>
0272 friend struct detail::common_eq;
0273 #endif
0274
0275 public:
0276 using iterator_concept = IteratorConcept;
0277 using iterator_category = iterator_concept;
0278 using value_type = std::remove_const_t<ValueType>;
0279 using reference = Reference;
0280 using pointer = detail::pointer_t<Pointer, iterator_concept>;
0281 using difference_type = DifferenceType;
0282
0283 template<typename D = Derived>
0284 constexpr auto operator*()
0285 noexcept(noexcept(*access::base(std::declval<D &>())))
0286 -> decltype(*access::base(std::declval<D &>()))
0287 {
0288 return *access::base(derived());
0289 }
0290 template<typename D = Derived>
0291 constexpr auto operator*() const
0292 noexcept(noexcept(*access::base(std::declval<D const &>())))
0293 -> decltype(*access::base(std::declval<D const &>()))
0294 {
0295 return *access::base(derived());
0296 }
0297
0298 template<typename D = Derived>
0299 constexpr auto operator->() noexcept(noexcept(
0300 detail::make_pointer<pointer, reference>(*std::declval<D &>())))
0301 -> decltype(
0302 detail::make_pointer<pointer, reference>(*std::declval<D &>()))
0303 {
0304 return detail::make_pointer<pointer, reference>(*derived());
0305 }
0306 template<typename D = Derived>
0307 constexpr auto operator->() const noexcept(noexcept(
0308 detail::make_pointer<pointer, reference>(
0309 *std::declval<D const &>())))
0310 -> decltype(
0311 detail::make_pointer<pointer, reference>(
0312 *std::declval<D const &>()))
0313 {
0314 return detail::make_pointer<pointer, reference>(*derived());
0315 }
0316
0317 template<typename D = Derived>
0318 constexpr auto operator[](difference_type i) const noexcept(noexcept(
0319 D(std::declval<D const &>()),
0320 std::declval<D &>() += i,
0321 *std::declval<D &>()))
0322 -> decltype(std::declval<D &>() += i, *std::declval<D &>())
0323 {
0324 D retval = derived();
0325 retval += i;
0326 return *retval;
0327 }
0328
0329 template<
0330 typename D = Derived,
0331 typename Enable =
0332 std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
0333 constexpr auto
0334 operator++() noexcept(noexcept(++access::base(std::declval<D &>())))
0335 -> decltype(
0336 ++access::base(std::declval<D &>()), std::declval<D &>())
0337 {
0338 ++access::base(derived());
0339 return derived();
0340 }
0341
0342 template<typename D = Derived>
0343 constexpr auto operator++() noexcept(
0344 noexcept(std::declval<D &>() += difference_type(1)))
0345 -> decltype(
0346 std::declval<D &>() += difference_type(1), std::declval<D &>())
0347 {
0348 derived() += difference_type(1);
0349 return derived();
0350 }
0351 template<typename D = Derived>
0352 constexpr auto operator++(int)noexcept(
0353 noexcept(D(std::declval<D &>()), ++std::declval<D &>()))
0354 -> std::remove_reference_t<decltype(
0355 D(std::declval<D &>()),
0356 ++std::declval<D &>(),
0357 std::declval<D &>())>
0358 {
0359 D retval = derived();
0360 ++derived();
0361 return retval;
0362 }
0363
0364 template<typename D = Derived>
0365 constexpr auto operator+=(difference_type n) noexcept(
0366 noexcept(access::base(std::declval<D &>()) += n))
0367 -> decltype(
0368 access::base(std::declval<D &>()) += n, std::declval<D &>())
0369 {
0370 access::base(derived()) += n;
0371 return derived();
0372 }
0373
0374 template<typename D = Derived>
0375 constexpr auto operator+(difference_type i) const
0376 noexcept(noexcept(D(std::declval<D &>()), std::declval<D &>() += i))
0377 -> std::remove_reference_t<decltype(
0378 D(std::declval<D &>()),
0379 std::declval<D &>() += i,
0380 std::declval<D &>())>
0381 {
0382 D retval = derived();
0383 retval += i;
0384 return retval;
0385 }
0386 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
0387 operator+(difference_type i, Derived it) noexcept
0388 {
0389 return it + i;
0390 }
0391
0392 template<
0393 typename D = Derived,
0394 typename Enable =
0395 std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
0396 constexpr auto
0397 operator--() noexcept(noexcept(--access::base(std::declval<D &>())))
0398 -> decltype(--access::base(std::declval<D &>()), std::declval<D &>())
0399 {
0400 --access::base(derived());
0401 return derived();
0402 }
0403
0404 template<typename D = Derived>
0405 constexpr auto operator--() noexcept(noexcept(
0406 D(std::declval<D &>()), std::declval<D &>() += -difference_type(1)))
0407 -> decltype(
0408 std::declval<D &>() += -difference_type(1), std::declval<D &>())
0409 {
0410 derived() += -difference_type(1);
0411 return derived();
0412 }
0413 template<typename D = Derived>
0414 constexpr auto operator--(int)noexcept(
0415 noexcept(D(std::declval<D &>()), --std::declval<D &>()))
0416 -> std::remove_reference_t<decltype(
0417 D(std::declval<D &>()),
0418 --std::declval<D &>(),
0419 std::declval<D &>())>
0420 {
0421 D retval = derived();
0422 --derived();
0423 return retval;
0424 }
0425
0426 template<typename D = Derived>
0427 constexpr D & operator-=(difference_type i) noexcept
0428 {
0429 derived() += -i;
0430 return derived();
0431 }
0432
0433 template<typename D = Derived>
0434 constexpr auto operator-(D other) const noexcept(noexcept(
0435 access::base(std::declval<D const &>()) - access::base(other)))
0436 -> decltype(
0437 access::base(std::declval<D const &>()) - access::base(other))
0438 {
0439 return access::base(derived()) - access::base(other);
0440 }
0441
0442 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
0443 operator-(Derived it, difference_type i) noexcept
0444 {
0445 Derived retval = it;
0446 retval += -i;
0447 return retval;
0448 }
0449 };
0450
0451
0452
0453
0454
0455 template<
0456 typename IteratorInterface1,
0457 typename IteratorInterface2,
0458 typename Enable =
0459 std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>>
0460 constexpr auto
0461 operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept
0462 -> decltype(
0463 access::base(std::declval<IteratorInterface1 &>()) ==
0464 access::base(std::declval<IteratorInterface2 &>()))
0465 {
0466 return access::base(lhs) == access::base(rhs);
0467 }
0468
0469
0470
0471
0472 template<
0473 typename IteratorInterface1,
0474 typename IteratorInterface2,
0475 typename Enable =
0476 std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>>
0477 constexpr auto
0478 operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
0479 noexcept(detail::common_diff(lhs, rhs)))
0480 -> decltype(
0481 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0)
0482 {
0483 return detail::common_diff(lhs, rhs) == 0;
0484 }
0485
0486
0487
0488 template<typename IteratorInterface1, typename IteratorInterface2>
0489 constexpr auto operator!=(
0490 IteratorInterface1 lhs,
0491 IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs)))
0492 -> decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs))
0493 {
0494 return !(lhs == rhs);
0495 }
0496
0497
0498
0499
0500 template<typename IteratorInterface1, typename IteratorInterface2>
0501 constexpr auto
0502 operator<(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
0503 noexcept(detail::common_diff(lhs, rhs)))
0504 -> decltype(
0505 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0)
0506 {
0507 return detail::common_diff(lhs, rhs) < 0;
0508 }
0509
0510
0511
0512
0513 template<typename IteratorInterface1, typename IteratorInterface2>
0514 constexpr auto
0515 operator<=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
0516 noexcept(detail::common_diff(lhs, rhs)))
0517 -> decltype(
0518 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0)
0519 {
0520 return detail::common_diff(lhs, rhs) <= 0;
0521 }
0522
0523
0524
0525
0526 template<typename IteratorInterface1, typename IteratorInterface2>
0527 constexpr auto
0528 operator>(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
0529 noexcept(detail::common_diff(lhs, rhs)))
0530 -> decltype(
0531 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0)
0532 {
0533 return detail::common_diff(lhs, rhs) > 0;
0534 }
0535
0536
0537
0538
0539 template<typename IteratorInterface1, typename IteratorInterface2>
0540 constexpr auto
0541 operator>=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
0542 noexcept(detail::common_diff(lhs, rhs)))
0543 -> decltype(
0544 v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0)
0545 {
0546 return detail::common_diff(lhs, rhs) >= 0;
0547 }
0548
0549
0550
0551
0552 template<
0553 typename Derived,
0554 typename IteratorConcept,
0555 typename ValueType,
0556 typename Reference = ValueType,
0557 typename DifferenceType = std::ptrdiff_t>
0558 using proxy_iterator_interface = iterator_interface<
0559 Derived,
0560 IteratorConcept,
0561 ValueType,
0562 Reference,
0563 proxy_arrow_result<Reference>,
0564 DifferenceType>;
0565
0566 }}}
0567
0568 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
0569
0570 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
0571
0572 namespace v2_dtl {
0573 template<typename Iterator>
0574 struct iter_concept;
0575
0576 template<typename Iterator>
0577 requires requires
0578 {
0579 typename std::iterator_traits<Iterator>::iterator_concept;
0580 }
0581 struct iter_concept<Iterator>
0582 {
0583 using type =
0584 typename std::iterator_traits<Iterator>::iterator_concept;
0585 };
0586
0587 template<typename Iterator>
0588 requires(
0589 !requires {
0590 typename std::iterator_traits<Iterator>::iterator_concept;
0591 } &&
0592 requires {
0593 typename std::iterator_traits<Iterator>::iterator_category;
0594 })
0595 struct iter_concept<Iterator>
0596 {
0597 using type =
0598 typename std::iterator_traits<Iterator>::iterator_category;
0599 };
0600
0601 template<typename Iterator>
0602 requires(
0603 !requires {
0604 typename std::iterator_traits<Iterator>::iterator_concept;
0605 } &&
0606 !requires {
0607 typename std::iterator_traits<Iterator>::iterator_category;
0608 })
0609 struct iter_concept<Iterator>
0610 {
0611 using type = std::random_access_iterator_tag;
0612 };
0613
0614 template<typename Iterator>
0615 struct iter_concept
0616 {};
0617
0618 template<typename Iterator>
0619 using iter_concept_t = typename iter_concept<Iterator>::type;
0620
0621 template<typename D, typename DifferenceType>
0622
0623 concept plus_eq = requires (D d) { d += DifferenceType(1); };
0624
0625
0626 template<typename D, typename D2 = D>
0627
0628 concept base_3way =
0629 #if defined(__cpp_impl_three_way_comparison)
0630 requires (D d, D2 d2) { access::base(d) <=> access::base(d2); };
0631 #else
0632 false;
0633 #endif
0634
0635
0636 template<typename D1, typename D2 = D1>
0637
0638 concept base_eq =
0639 requires (D1 d1, D2 d2) { access::base(d1) == access::base(d2); };
0640
0641
0642 template<typename D, typename D2 = D>
0643
0644 concept iter_sub = requires (D d, D2 d2) {
0645 typename D::difference_type;
0646 {d - d2} -> std::convertible_to<typename D::difference_type>;
0647 };
0648
0649
0650
0651
0652
0653
0654 template<typename IteratorConcept, typename ReferenceType>
0655 constexpr auto category_tag()
0656 {
0657 if constexpr (std::is_base_of_v<
0658 std::forward_iterator_tag,
0659 IteratorConcept>) {
0660 if constexpr (!std::is_reference_v<ReferenceType>) {
0661 return std::input_iterator_tag{};
0662 } else if constexpr (std::is_base_of_v<
0663 std::random_access_iterator_tag,
0664 IteratorConcept>) {
0665 return std::random_access_iterator_tag{};
0666 } else if constexpr (std::is_base_of_v<
0667 std::bidirectional_iterator_tag,
0668 IteratorConcept>) {
0669 return std::bidirectional_iterator_tag{};
0670 } else {
0671 return std::forward_iterator_tag{};
0672 }
0673 } else {
0674 return 0;
0675 }
0676 }
0677 template<
0678 typename IteratorConcept,
0679 typename ReferenceType,
0680 typename IteratorCategory =
0681 decltype(v2_dtl::
0682 category_tag<IteratorConcept, ReferenceType>())>
0683 struct iterator_category_base
0684 {
0685 using iterator_category = IteratorCategory;
0686 };
0687
0688 template<typename IteratorConcept, typename ReferenceType>
0689 struct iterator_category_base<IteratorConcept, ReferenceType, int>
0690 {};
0691
0692 template<typename IteratorConcept, typename ReferenceType>
0693 constexpr bool non_input_tag()
0694 {
0695 if (std::same_as<IteratorConcept, std::input_iterator_tag>)
0696 return false;
0697 using tag_t =
0698 decltype(v2_dtl::
0699 category_tag<IteratorConcept, ReferenceType>());
0700 return !std::same_as<tag_t, std::input_iterator_tag>;
0701 }
0702 }
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714 template<
0715 typename D,
0716 typename IteratorConcept,
0717 typename ValueType,
0718 typename Reference = ValueType &,
0719 typename Pointer = ValueType *,
0720 typename DifferenceType = std::ptrdiff_t>
0721 requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
0722 struct iterator_interface
0723 : v2_dtl::iterator_category_base<IteratorConcept, Reference>
0724 {
0725 private:
0726 constexpr D& derived() noexcept {
0727 return static_cast<D&>(*this);
0728 }
0729 constexpr const D& derived() const noexcept {
0730 return static_cast<const D&>(*this);
0731 }
0732
0733 public:
0734 using iterator_concept = IteratorConcept;
0735 using value_type = std::remove_const_t<ValueType>;
0736 using reference = Reference;
0737 using pointer = detail::pointer_t<Pointer, iterator_concept>;
0738 using difference_type = DifferenceType;
0739
0740 constexpr decltype(auto) operator*()
0741 requires requires (D d) { *access::base(d); } {
0742 return *access::base(derived());
0743 }
0744 constexpr decltype(auto) operator*() const
0745 requires requires (D const d) { *access::base(d); } {
0746 return *access::base(derived());
0747 }
0748
0749 constexpr auto operator->()
0750 requires (!std::same_as<pointer, void> && std::is_reference_v<reference> &&
0751 requires (D d) { *d; }) {
0752 return detail::make_pointer<pointer, reference>(*derived());
0753 }
0754 constexpr auto operator->() const
0755 requires (!std::same_as<pointer, void> && std::is_reference_v<reference> &&
0756 requires (D const d) { *d; }) {
0757 return detail::make_pointer<pointer, reference>(*derived());
0758 }
0759
0760 constexpr decltype(auto) operator[](difference_type n) const
0761 requires requires (D const d) { d + n; } {
0762 D retval = derived();
0763 retval += n;
0764 return *retval;
0765 }
0766
0767 constexpr decltype(auto) operator++()
0768 requires requires (D d) { ++access::base(d); } &&
0769 (!v2_dtl::plus_eq<D, difference_type>) {
0770 ++access::base(derived());
0771 return derived();
0772 }
0773 constexpr decltype(auto) operator++()
0774 requires requires (D d) { d += difference_type(1); } {
0775 return derived() += difference_type(1);
0776 }
0777 constexpr auto operator++(int) requires requires (D d) { ++d; } {
0778 if constexpr (std::is_same_v<IteratorConcept, std::input_iterator_tag>){
0779 ++derived();
0780 } else {
0781 D retval = derived();
0782 ++derived();
0783 return retval;
0784 }
0785 }
0786 constexpr decltype(auto) operator+=(difference_type n)
0787 requires requires (D d) { access::base(d) += n; } {
0788 access::base(derived()) += n;
0789 return derived();
0790 }
0791
0792 constexpr decltype(auto) operator--()
0793 requires requires (D d) { --access::base(d); } &&
0794 (!v2_dtl::plus_eq<D, difference_type>) {
0795 --access::base(derived());
0796 return derived();
0797 }
0798 constexpr decltype(auto) operator--()
0799 requires requires (D d) { d += -difference_type(1); } {
0800 return derived() += -difference_type(1);
0801 }
0802 constexpr auto operator--(int) requires requires (D d) { --d; } {
0803 D retval = derived();
0804 --derived();
0805 return retval;
0806 }
0807 constexpr decltype(auto) operator-=(difference_type n)
0808 requires requires (D d) { d += -n; } {
0809 return derived() += -n;
0810 }
0811 };
0812
0813 namespace v2_dtl {
0814 template<
0815 typename D,
0816 typename IteratorConcept,
0817 typename ValueType,
0818 typename Reference,
0819 typename Pointer,
0820 typename DifferenceType>
0821 void derived_iterator(v2::iterator_interface<
0822 D,
0823 IteratorConcept,
0824 ValueType,
0825 Reference,
0826 Pointer,
0827 DifferenceType> const &);
0828
0829 template<typename D>
0830 concept derived_iter = requires (D d) { v2_dtl::derived_iterator(d); };
0831 }
0832
0833 template<typename D>
0834 constexpr auto operator+(D it, typename D::difference_type n)
0835 requires v2_dtl::derived_iter<D> && requires { it += n; }
0836 { return it += n; }
0837 template<typename D>
0838 constexpr auto operator+(typename D::difference_type n, D it)
0839 requires v2_dtl::derived_iter<D> && requires { it += n; }
0840 { return it += n; }
0841
0842 template<typename D1, typename D2>
0843 constexpr auto operator-(D1 lhs, D2 rhs)
0844 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
0845 requires { access::base(lhs) - access::base(rhs); }
0846 { return access::base(lhs) - access::base(rhs); }
0847 template<typename D>
0848 constexpr auto operator-(D it, typename D::difference_type n)
0849 requires v2_dtl::derived_iter<D> && requires { it += -n; }
0850 { return it += -n; }
0851
0852 #if defined(__cpp_lib_three_way_comparison)
0853 template<typename D1, typename D2>
0854 constexpr auto operator<=>(D1 lhs, D2 rhs)
0855 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
0856 (v2_dtl::base_3way<D1, D2> || v2_dtl::iter_sub<D1, D2>) {
0857 if constexpr (v2_dtl::base_3way<D1, D2>) {
0858 return access::base(lhs) <=> access::base(rhs);
0859 } else {
0860 using diff_type = typename D1::difference_type;
0861 diff_type const diff = rhs - lhs;
0862 return diff < diff_type(0) ? std::strong_ordering::less :
0863 diff_type(0) < diff ? std::strong_ordering::greater :
0864 std::strong_ordering::equal;
0865 }
0866 }
0867 #endif
0868 template<typename D1, typename D2>
0869 constexpr bool operator<(D1 lhs, D2 rhs)
0870 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
0871 { return (lhs - rhs) < typename D1::difference_type(0); }
0872 template<typename D1, typename D2>
0873 constexpr bool operator<=(D1 lhs, D2 rhs)
0874 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
0875 { return (lhs - rhs) <= typename D1::difference_type(0); }
0876 template<typename D1, typename D2>
0877 constexpr bool operator>(D1 lhs, D2 rhs)
0878 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
0879 { return (lhs - rhs) > typename D1::difference_type(0); }
0880 template<typename D1, typename D2>
0881 constexpr bool operator>=(D1 lhs, D2 rhs)
0882 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> && v2_dtl::iter_sub<D1, D2>
0883 { return (lhs - rhs) >= typename D1::difference_type(0); }
0884
0885 template<typename D1, typename D2>
0886 constexpr bool operator==(D1 lhs, D2 rhs)
0887 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2> &&
0888 detail::interoperable<D1, D2>::value &&
0889 (v2_dtl::base_eq<D1, D2> || v2_dtl::iter_sub<D1, D2>) {
0890 if constexpr (v2_dtl::base_eq<D1, D2>) {
0891 return (access::base(lhs) == access::base(rhs));
0892 } else if constexpr (v2_dtl::iter_sub<D1, D2>) {
0893 return (lhs - rhs) == typename D1::difference_type(0);
0894 }
0895 }
0896
0897 template<typename D1, typename D2>
0898 constexpr auto operator!=(D1 lhs, D2 rhs) -> decltype(!(lhs == rhs))
0899 requires v2_dtl::derived_iter<D1> && v2_dtl::derived_iter<D2>
0900 { return !(lhs == rhs); }
0901
0902
0903
0904
0905
0906
0907 template<
0908 typename Derived,
0909 typename IteratorConcept,
0910 typename ValueType,
0911 typename Reference = ValueType,
0912 typename DifferenceType = std::ptrdiff_t>
0913 using proxy_iterator_interface = iterator_interface<
0914 Derived,
0915 IteratorConcept,
0916 ValueType,
0917 Reference,
0918 proxy_arrow_result<Reference>,
0919 DifferenceType>;
0920
0921 }}}
0922
0923 #endif
0924
0925 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS
0926
0927 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
0928
0929
0930
0931
0932
0933 template<
0934 typename IteratorConcept,
0935 typename ValueType,
0936 typename Reference = ValueType &,
0937 typename Pointer = ValueType *,
0938 typename DifferenceType = std::ptrdiff_t>
0939 struct iterator_interface
0940 : v2::v2_dtl::iterator_category_base<IteratorConcept, Reference>
0941 {
0942 using iterator_concept = IteratorConcept;
0943 using value_type = std::remove_const_t<ValueType>;
0944 using reference = Reference;
0945 using pointer = detail::pointer_t<Pointer, iterator_concept>;
0946 using difference_type = DifferenceType;
0947
0948 constexpr decltype(auto) operator*(this auto&& self)
0949 requires requires { *access::base(self); } {
0950 return *access::base(self);
0951 }
0952
0953 constexpr auto operator->(this auto&& self)
0954 requires (!std::same_as<pointer, void>) && std::is_reference_v<reference> && requires { *self; } {
0955 return detail::make_pointer<pointer, reference>(*self);
0956 }
0957
0958 constexpr decltype(auto) operator[](this auto const& self, difference_type n)
0959 requires requires { self + n; } {
0960 auto retval = self;
0961 retval = retval + n;
0962 return *retval;
0963 }
0964
0965 constexpr decltype(auto) operator++(this auto& self)
0966 requires requires { ++access::base(self); } && (!requires { self += difference_type(1); }) {
0967 ++access::base(self);
0968 return self;
0969 }
0970 constexpr decltype(auto) operator++(this auto& self)
0971 requires requires { self += difference_type(1); } {
0972 return self += difference_type(1);
0973 }
0974 constexpr auto operator++(this auto& self, int) requires requires { ++self; } {
0975 if constexpr (std::is_same_v<IteratorConcept, std::input_iterator_tag>){
0976 ++self;
0977 } else {
0978 auto retval = self;
0979 ++self;
0980 return retval;
0981 }
0982 }
0983 constexpr decltype(auto) operator+=(this auto& self, difference_type n)
0984 requires requires { access::base(self) += n; } {
0985 access::base(self) += n;
0986 return self;
0987 }
0988
0989 constexpr decltype(auto) operator--(this auto& self)
0990 requires requires { --access::base(self); } && (!requires { self += difference_type(1); }) {
0991 --access::base(self);
0992 return self;
0993 }
0994 constexpr decltype(auto) operator--(this auto& self)
0995 requires requires { self += -difference_type(1); } {
0996 return self += -difference_type(1);
0997 }
0998 constexpr auto operator--(this auto& self, int) requires requires { --self; } {
0999 auto retval = self;
1000 --self;
1001 return retval;
1002 }
1003 constexpr decltype(auto) operator-=(this auto& self, difference_type n)
1004 requires requires { self += -n; } {
1005 return self += -n;
1006 }
1007 };
1008
1009 namespace v3_dtl {
1010 template<
1011 typename IteratorConcept,
1012 typename ValueType,
1013 typename Reference,
1014 typename Pointer,
1015 typename DifferenceType>
1016 void derived_iterator(v3::iterator_interface<
1017 IteratorConcept,
1018 ValueType,
1019 Reference,
1020 Pointer,
1021 DifferenceType> const &);
1022
1023 template<typename D>
1024 concept derived_iter = requires (D d) { v3_dtl::derived_iterator(d); };
1025 }
1026
1027 template<typename D>
1028 constexpr auto operator+(D it, typename D::difference_type n)
1029 requires v3_dtl::derived_iter<D> && requires { it += n; }
1030 { return it += n; }
1031 template<typename D>
1032 constexpr auto operator+(typename D::difference_type n, D it)
1033 requires v3_dtl::derived_iter<D> && requires { it += n; }
1034 { return it += n; }
1035
1036 template<typename D1, typename D2>
1037 constexpr auto operator-(D1 lhs, D2 rhs)
1038 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
1039 requires { access::base(lhs) - access::base(rhs); }
1040 { return access::base(lhs) - access::base(rhs); }
1041 template<typename D>
1042 constexpr auto operator-(D it, typename D::difference_type n)
1043 requires v3_dtl::derived_iter<D> && requires { it += -n; }
1044 { return it += -n; }
1045
1046 #if defined(__cpp_lib_three_way_comparison)
1047 template<typename D1, typename D2>
1048 constexpr auto operator<=>(D1 lhs, D2 rhs)
1049 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
1050 (v2::v2_dtl::base_3way<D1, D2> || v2::v2_dtl::iter_sub<D1, D2>) {
1051 if constexpr (v2::v2_dtl::base_3way<D1, D2>) {
1052 return access::base(lhs) <=> access::base(rhs);
1053 } else {
1054 using diff_type = typename D1::difference_type;
1055 diff_type const diff = rhs - lhs;
1056 return diff < diff_type(0) ? std::strong_ordering::less :
1057 diff_type(0) < diff ? std::strong_ordering::greater :
1058 std::strong_ordering::equal;
1059 }
1060 }
1061 #endif
1062 template<typename D1, typename D2>
1063 constexpr bool operator<(D1 lhs, D2 rhs)
1064 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
1065 { return (lhs - rhs) < typename D1::difference_type(0); }
1066 template<typename D1, typename D2>
1067 constexpr bool operator<=(D1 lhs, D2 rhs)
1068 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
1069 { return (lhs - rhs) <= typename D1::difference_type(0); }
1070 template<typename D1, typename D2>
1071 constexpr bool operator>(D1 lhs, D2 rhs)
1072 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
1073 { return (lhs - rhs) > typename D1::difference_type(0); }
1074 template<typename D1, typename D2>
1075 constexpr bool operator>=(D1 lhs, D2 rhs)
1076 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> && v2::v2_dtl::iter_sub<D1, D2>
1077 { return (lhs - rhs) >= typename D1::difference_type(0); }
1078
1079 template<typename D1, typename D2>
1080 constexpr bool operator==(D1 lhs, D2 rhs)
1081 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2> &&
1082 detail::interoperable<D1, D2>::value &&
1083 (v2::v2_dtl::base_eq<D1, D2> || v2::v2_dtl::iter_sub<D1, D2>) {
1084 if constexpr (v2::v2_dtl::base_eq<D1, D2>) {
1085 return (access::base(lhs) == access::base(rhs));
1086 } else if constexpr (v2::v2_dtl::iter_sub<D1, D2>) {
1087 return (lhs - rhs) == typename D1::difference_type(0);
1088 }
1089 }
1090
1091 template<typename D1, typename D2>
1092 constexpr auto operator!=(D1 lhs, D2 rhs) -> decltype(!(lhs == rhs))
1093 requires v3_dtl::derived_iter<D1> && v3_dtl::derived_iter<D2>
1094 { return !(lhs == rhs); }
1095
1096
1097
1098
1099
1100
1101 template<
1102 typename IteratorConcept,
1103 typename ValueType,
1104 typename Reference = ValueType,
1105 typename DifferenceType = std::ptrdiff_t>
1106 using proxy_iterator_interface = iterator_interface<
1107 IteratorConcept,
1108 ValueType,
1109 Reference,
1110 proxy_arrow_result<Reference>,
1111 DifferenceType>;
1112
1113 }}}
1114
1115 #endif
1116
1117 #ifdef BOOST_STL_INTERFACES_DOXYGEN
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
1141 iter, category, concept, value_type, reference, pointer, difference_type)
1142
1143 #else
1144
1145 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
1146 type, concept_name) \
1147 static_assert(concept_name<type>, "");
1148
1149 #if BOOST_STL_INTERFACES_USE_CONCEPTS
1150 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name) \
1151 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL(iter, concept_name)
1152 #else
1153 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name)
1154 #endif
1155
1156 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
1157 iter, category, value_t, ref, ptr, diff_t) \
1158 static_assert( \
1159 std::is_same< \
1160 typename std::iterator_traits<iter>::value_type, \
1161 value_t>::value, \
1162 ""); \
1163 static_assert( \
1164 std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \
1165 value, \
1166 ""); \
1167 static_assert( \
1168 std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \
1169 value, \
1170 ""); \
1171 static_assert( \
1172 std::is_same< \
1173 typename std::iterator_traits<iter>::difference_type, \
1174 diff_t>::value, \
1175 "");
1176
1177 #define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
1178 iter, category, concept, value_type, reference, pointer, difference_type) \
1179 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
1180 iter, category, value_type, reference, pointer, difference_type)
1181 #endif
1182
1183 #endif