Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:53:49

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