File indexing completed on 2025-10-31 09:13:57
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 
0014 
0015 #ifndef RANGES_V3_DETAIL_RANGE_ACCESS_HPP
0016 #define RANGES_V3_DETAIL_RANGE_ACCESS_HPP
0017 
0018 #include <cstddef>
0019 #include <utility>
0020 
0021 #include <meta/meta.hpp>
0022 
0023 #include <concepts/concepts.hpp>
0024 
0025 #include <range/v3/range_fwd.hpp>
0026 
0027 #include <range/v3/iterator/concepts.hpp>
0028 
0029 #include <range/v3/detail/prologue.hpp>
0030 
0031 namespace ranges
0032 {
0033     
0034     
0035     struct range_access
0036     {
0037         
0038     private:
0039         template<typename T>
0040         static std::false_type single_pass_2_(long);
0041         template<typename T>
0042         static typename T::single_pass single_pass_2_(int);
0043 
0044         template<typename T>
0045         struct single_pass_
0046         {
0047             using type = decltype(range_access::single_pass_2_<T>(42));
0048         };
0049 
0050         template<typename T>
0051         static std::false_type contiguous_2_(long);
0052         template<typename T>
0053         static typename T::contiguous contiguous_2_(int);
0054 
0055         template<typename T>
0056         struct contiguous_
0057         {
0058             using type = decltype(range_access::contiguous_2_<T>(42));
0059         };
0060 
0061         template<typename T>
0062         static basic_mixin<T> mixin_base_2_(long);
0063         template<typename T>
0064         static typename T::mixin mixin_base_2_(int);
0065 
0066         template<typename Cur>
0067         struct mixin_base_
0068         {
0069             using type = decltype(range_access::mixin_base_2_<Cur>(42));
0070         };
0071 
0072 
0073     public:
0074         template<typename Cur>
0075         using single_pass_t = meta::_t<single_pass_<Cur>>;
0076 
0077         template<typename Cur>
0078         using contiguous_t = meta::_t<contiguous_<Cur>>;
0079 
0080         template<typename Cur>
0081         using mixin_base_t = meta::_t<mixin_base_<Cur>>;
0082 
0083         
0084         template<typename Rng>
0085         static constexpr auto CPP_auto_fun(begin_cursor)(Rng &rng)
0086         (
0087             return rng.begin_cursor()
0088         )
0089         template<typename Rng>
0090         static constexpr auto CPP_auto_fun(end_cursor)(Rng &rng)
0091         (
0092             return rng.end_cursor()
0093         )
0094 
0095         template<typename Rng>
0096         static constexpr auto CPP_auto_fun(begin_adaptor)(Rng &rng)
0097         (
0098             return rng.begin_adaptor()
0099         )
0100         template<typename Rng>
0101         static constexpr auto CPP_auto_fun(end_adaptor)(Rng &rng)
0102         (
0103             return rng.end_adaptor()
0104         )
0105 
0106         template<typename Cur>
0107         static constexpr auto CPP_auto_fun(read)(Cur const &pos)
0108         (
0109             return pos.read()
0110         )
0111         template<typename Cur>
0112         static constexpr auto CPP_auto_fun(arrow)(Cur const &pos)
0113         (
0114             return pos.arrow()
0115         )
0116         template<typename Cur>
0117         static constexpr auto CPP_auto_fun(move)(Cur const &pos)
0118         (
0119             return pos.move()
0120         )
0121         template<typename Cur, typename T>
0122         static constexpr auto CPP_auto_fun(write)(Cur &pos, T &&t)
0123         (
0124             return pos.write((T &&) t)
0125         )
0126         template<typename Cur>
0127         static constexpr auto CPP_auto_fun(next)(Cur & pos)
0128         (
0129             return pos.next()
0130         )
0131         template<typename Cur, typename O>
0132         static constexpr auto CPP_auto_fun(equal)(Cur const &pos, O const &other)
0133         (
0134             return pos.equal(other)
0135         )
0136         template<typename Cur>
0137         static constexpr auto CPP_auto_fun(prev)(Cur & pos)
0138         (
0139             return pos.prev()
0140         )
0141         template<typename Cur, typename D>
0142         static constexpr auto CPP_auto_fun(advance)(Cur & pos, D n)
0143         (
0144             return pos.advance(n)
0145         )
0146         template<typename Cur, typename O>
0147         static constexpr auto CPP_auto_fun(distance_to)(Cur const &pos, O const &other)
0148         (
0149             return pos.distance_to(other)
0150         )
0151 
0152     private:
0153         template<typename Cur>
0154         using sized_cursor_difference_t = decltype(
0155             range_access::distance_to(std::declval<Cur>(), std::declval<Cur>()));
0156         
0157 
0158         template<typename T>
0159         static std::ptrdiff_t cursor_difference_2_(detail::ignore_t);
0160         template<typename T>
0161         static sized_cursor_difference_t<T> cursor_difference_2_(long);
0162         template<typename T>
0163         static typename T::difference_type cursor_difference_2_(int);
0164 
0165         template<typename T>
0166         using cursor_reference_t = decltype(std::declval<T const &>().read());
0167 
0168         template<typename T>
0169         static meta::id<uncvref_t<cursor_reference_t<T>>> cursor_value_2_(long);
0170         template<typename T>
0171         static meta::id<typename T::value_type> cursor_value_2_(int);
0172 
0173 #ifdef RANGES_WORKAROUND_CWG_1554
0174         template<typename Cur>
0175         struct cursor_difference
0176         {
0177             using type = decltype(range_access::cursor_difference_2_<Cur>(42));
0178         };
0179 
0180         template<typename Cur>
0181         struct cursor_value : decltype(range_access::cursor_value_2_<Cur>(42))
0182         {};
0183 #endif 
0184     public:
0185 #ifdef RANGES_WORKAROUND_CWG_1554
0186         template<typename Cur>
0187         using cursor_difference_t = meta::_t<cursor_difference<Cur>>;
0188 
0189         template<typename Cur>
0190         using cursor_value_t = meta::_t<cursor_value<Cur>>;
0191 #else  
0192         template<typename Cur>
0193         using cursor_difference_t = decltype(range_access::cursor_difference_2_<Cur>(42));
0194 
0195         template<typename Cur>
0196         using cursor_value_t = meta::_t<decltype(range_access::cursor_value_2_<Cur>(42))>;
0197 #endif 
0198 
0199         template<typename Cur>
0200         static constexpr Cur & pos(basic_iterator<Cur> & it) noexcept
0201         {
0202             return it.pos();
0203         }
0204         template<typename Cur>
0205         static constexpr Cur const & pos(basic_iterator<Cur> const & it) noexcept
0206         {
0207             return it.pos();
0208         }
0209         template<typename Cur>
0210         static constexpr Cur && pos(basic_iterator<Cur> && it) noexcept
0211         {
0212             return detail::move(it.pos());
0213         }
0214 
0215         template<typename Cur>
0216         static constexpr Cur cursor(basic_iterator<Cur> it)
0217         {
0218             return std::move(it.pos());
0219         }
0220         
0221     };
0222     
0223 
0224     
0225     namespace detail
0226     {
0227         
0228         
0229         
0230         
0231         
0232         
0233         template<typename T>
0234         CPP_concept cursor =
0235             semiregular<T> && semiregular<range_access::mixin_base_t<T>> &&
0236             constructible_from<range_access::mixin_base_t<T>, T> &&
0237             constructible_from<range_access::mixin_base_t<T>, T const &>;
0238             
0239             
0240             
0241 
0242         
0243         
0244         template<typename T>
0245         CPP_requires(has_cursor_next_,
0246             requires(T & t)
0247             (
0248                 range_access::next(t)
0249             ));
0250         
0251         
0252         template<typename T>
0253         CPP_concept has_cursor_next = CPP_requires_ref(detail::has_cursor_next_, T);
0254 
0255         
0256         
0257         template<typename S, typename C>
0258         CPP_requires(sentinel_for_cursor_,
0259             requires(S & s, C & c) 
0260             (
0261                 range_access::equal(c, s),
0262                 concepts::requires_<convertible_to<decltype(
0263                     range_access::equal(c, s)), bool>>
0264             ));
0265         
0266         
0267         template<typename S, typename C>
0268         CPP_concept sentinel_for_cursor =
0269             semiregular<S> &&
0270             cursor<C> &&
0271             CPP_requires_ref(detail::sentinel_for_cursor_, S, C);
0272 
0273         
0274         
0275         template<typename T>
0276         CPP_requires(readable_cursor_,
0277             requires(T & t) 
0278             (
0279                 range_access::read(t)
0280             ));
0281         
0282         
0283         template<typename T>
0284         CPP_concept readable_cursor = CPP_requires_ref(detail::readable_cursor_, T);
0285 
0286         
0287         
0288         template<typename T>
0289         CPP_requires(has_cursor_arrow_,
0290             requires(T const & t) 
0291             (
0292                 range_access::arrow(t)
0293             ));
0294         
0295         
0296         template<typename T>
0297         CPP_concept has_cursor_arrow = CPP_requires_ref(detail::has_cursor_arrow_, T);
0298 
0299         
0300         
0301         template<typename T, typename U>
0302         CPP_requires(writable_cursor_,
0303             requires(T & t, U && u) 
0304             (
0305                 range_access::write(t, (U &&) u)
0306             ));
0307         
0308         
0309         template<typename T, typename U>
0310         CPP_concept writable_cursor =
0311             CPP_requires_ref(detail::writable_cursor_, T, U);
0312 
0313         
0314         
0315         template<typename S, typename C>
0316         CPP_requires(sized_sentinel_for_cursor_,
0317             requires(S & s, C & c) 
0318             (
0319                 range_access::distance_to(c, s),
0320                 concepts::requires_<signed_integer_like_<decltype(
0321                     range_access::distance_to(c, s))>>
0322             )
0323         );
0324         
0325         
0326         template<typename S, typename C>
0327         CPP_concept sized_sentinel_for_cursor =
0328             sentinel_for_cursor<S, C> &&
0329             CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
0330 
0331         
0332         
0333         template<typename T, typename U>
0334         CPP_concept output_cursor =
0335             writable_cursor<T, U> && cursor<T>;
0336 
0337         
0338         
0339         template<typename T>
0340         CPP_concept input_cursor =
0341             readable_cursor<T> && cursor<T> && has_cursor_next<T>;
0342 
0343         
0344         
0345         template<typename T>
0346         CPP_concept forward_cursor =
0347             input_cursor<T> && sentinel_for_cursor<T, T> &&
0348             !range_access::single_pass_t<uncvref_t<T>>::value;
0349 
0350         
0351         
0352         template<typename T>
0353         CPP_requires(bidirectional_cursor_,
0354             requires(T & t) 
0355             (
0356                 range_access::prev(t)
0357             ));
0358         
0359         
0360         template<typename T>
0361         CPP_concept bidirectional_cursor =
0362             forward_cursor<T> &&
0363             CPP_requires_ref(detail::bidirectional_cursor_, T);
0364 
0365         
0366         
0367         template<typename T>
0368         CPP_requires(random_access_cursor_,
0369             requires(T & t) 
0370             (
0371                 range_access::advance(t, range_access::distance_to(t, t))
0372             ));
0373         
0374         
0375         template<typename T>
0376         CPP_concept random_access_cursor =
0377             bidirectional_cursor<T> && 
0378             sized_sentinel_for_cursor<T, T> && 
0379             CPP_requires_ref(detail::random_access_cursor_, T);
0380 
0381         template(class T)(
0382             requires std::is_lvalue_reference<T>::value)
0383         void is_lvalue_reference(T&&);
0384 
0385         
0386         
0387         template<typename T>
0388         CPP_requires(contiguous_cursor_,
0389             requires(T & t) 
0390             (
0391                 detail::is_lvalue_reference(range_access::read(t))
0392             ));
0393         
0394         
0395         template<typename T>
0396         CPP_concept contiguous_cursor =
0397             random_access_cursor<T> && 
0398             range_access::contiguous_t<uncvref_t<T>>::value && 
0399             CPP_requires_ref(detail::contiguous_cursor_, T);
0400         
0401 
0402         template<typename Cur, bool IsReadable>
0403         RANGES_INLINE_VAR constexpr bool is_writable_cursor_ = true;
0404 
0405         template<typename Cur>
0406         RANGES_INLINE_VAR constexpr bool is_writable_cursor_<Cur, true> =
0407             (bool) writable_cursor<Cur, range_access::cursor_value_t<Cur>>;
0408 
0409         template<typename Cur>
0410         RANGES_INLINE_VAR constexpr bool is_writable_cursor_v =
0411             is_writable_cursor_<Cur, (bool)readable_cursor<Cur>>;
0412     } 
0413     
0414 } 
0415 
0416 #include <range/v3/detail/epilogue.hpp>
0417 
0418 #endif