Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:32:18

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_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     /** 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_STL_INTERFACES_USE_CONCEPTS
0050     // clang-format off
0051         requires std::is_object_v<T>
0052 #endif
0053     struct proxy_arrow_result
0054     // clang-format on
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     /** A CRTP template that one may derive from to make defining iterators
0178         easier.
0179 
0180         The template parameter `D` for `iterator_interface` may be an
0181         incomplete type.  Before any member of the resulting specialization of
0182         `iterator_interface` other than special member functions is
0183         referenced, `D` shall be complete, and model
0184         `std::derived_from<iterator_interface<D>>`. */
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     /** Implementation of `operator==()`, implemented in terms of the iterator
0452         underlying IteratorInterface, for all iterators derived from
0453         `iterator_interface`, except those with an iterator category derived
0454         from `std::random_access_iterator_tag`.  */
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     /** Implementation of `operator==()` for all iterators derived from
0470         `iterator_interface` that have an iterator category derived from
0471         `std::random_access_iterator_tag`.  */
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     /** Implementation of `operator!=()` for all iterators derived from
0487         `iterator_interface`.  */
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     /** Implementation of `operator<()` for all iterators derived from
0498         `iterator_interface` that have an iterator category derived from
0499         `std::random_access_iterator_tag`.  */
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     /** Implementation of `operator<=()` for all iterators derived from
0511         `iterator_interface` that have an iterator category derived from
0512         `std::random_access_iterator_tag`.  */
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     /** Implementation of `operator>()` for all iterators derived from
0524         `iterator_interface` that have an iterator category derived from
0525         `std::random_access_iterator_tag`.  */
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     /** Implementation of `operator>=()` for all iterators derived from
0537         `iterator_interface` that have an iterator category derived from
0538         `std::random_access_iterator_tag`.  */
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     /** A template alias useful for defining proxy iterators.  \see
0551         `iterator_interface`. */
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         // clang-format off
0623         concept plus_eq = requires (D d) { d += DifferenceType(1); };
0624         // clang-format on
0625 
0626         template<typename D, typename D2 = D>
0627         // clang-format off
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         // clang-format on
0635 
0636         template<typename D1, typename D2 = D1>
0637         // clang-format off
0638         concept base_eq =
0639             requires (D1 d1, D2 d2) { access::base(d1) == access::base(d2); };
0640         // clang-format on
0641 
0642         template<typename D, typename D2 = D>
0643         // clang-format off
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         // clang-format on
0649 
0650         // This iterator concept -> category mapping scheme follows the one
0651         // from zip_transform_view; see
0652         // https://eel.is/c++draft/range.zip.transform.iterator#1.
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; // int means "no tag"
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     // clang-format off
0705 
0706     /** A CRTP template that one may derive from to make defining iterators
0707         easier.
0708 
0709         The template parameter `D` for `iterator_interface` may be an
0710         incomplete type.  Before any member of the resulting specialization of
0711         `iterator_interface` other than special member functions is
0712         referenced, `D` shall be complete, and model
0713         `std::derived_from<iterator_interface<D>>`. */
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     // clang-format on
0903 
0904 
0905     /** A template alias useful for defining proxy iterators.  \see
0906         `iterator_interface`. */
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     // clang-format off
0930 
0931     /** A base template that one may derive from to make defining iterators
0932         easier. */
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     // clang-format on
1097 
1098 
1099     /** A template alias useful for defining proxy iterators.  \see
1100         `iterator_interface`. */
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 /** `static_asserts` that type `type` models concept `concept_name`.  This is
1120     useful for checking that an iterator, view, etc. that you write using one
1121     of the *`_interface` templates models the right C++ concept.
1122 
1123     For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter,
1124     std::input_iterator)`.
1125 
1126     \note This macro expands to nothing when `__cpp_lib_concepts` is not
1127     defined. */
1128 #define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)
1129 
1130 /** `static_asserts` that the types of all typedefs in
1131     `std::iterator_traits<iter>` match the remaining macro parameters.  This
1132     is useful for checking that an iterator you write using
1133     `iterator_interface` has the correct iterator traits.
1134 
1135     For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
1136     std::input_iterator_tag, std::input_iterator, int, int &, int *, std::ptrdiff_t)`.
1137 
1138     \note This macro ignores the `concept` parameter when `__cpp_lib_concepts`
1139     is not defined. */
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