Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:49

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