/// \file // Range v3 library // // Copyright Eric Niebler 2014-present // Copyright Casey Carter 2016 // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_DETAIL_RANGE_ACCESS_HPP #define RANGES_V3_DETAIL_RANGE_ACCESS_HPP #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-views /// @{ struct range_access { /// \cond private: template static std::false_type single_pass_2_(long); template static typename T::single_pass single_pass_2_(int); template struct single_pass_ { using type = decltype(range_access::single_pass_2_(42)); }; template static std::false_type contiguous_2_(long); template static typename T::contiguous contiguous_2_(int); template struct contiguous_ { using type = decltype(range_access::contiguous_2_(42)); }; template static basic_mixin mixin_base_2_(long); template static typename T::mixin mixin_base_2_(int); template struct mixin_base_ { using type = decltype(range_access::mixin_base_2_(42)); }; public: template using single_pass_t = meta::_t>; template using contiguous_t = meta::_t>; template using mixin_base_t = meta::_t>; // clang-format off template static constexpr auto CPP_auto_fun(begin_cursor)(Rng &rng) ( return rng.begin_cursor() ) template static constexpr auto CPP_auto_fun(end_cursor)(Rng &rng) ( return rng.end_cursor() ) template static constexpr auto CPP_auto_fun(begin_adaptor)(Rng &rng) ( return rng.begin_adaptor() ) template static constexpr auto CPP_auto_fun(end_adaptor)(Rng &rng) ( return rng.end_adaptor() ) template static constexpr auto CPP_auto_fun(read)(Cur const &pos) ( return pos.read() ) template static constexpr auto CPP_auto_fun(arrow)(Cur const &pos) ( return pos.arrow() ) template static constexpr auto CPP_auto_fun(move)(Cur const &pos) ( return pos.move() ) template static constexpr auto CPP_auto_fun(write)(Cur &pos, T &&t) ( return pos.write((T &&) t) ) template static constexpr auto CPP_auto_fun(next)(Cur & pos) ( return pos.next() ) template static constexpr auto CPP_auto_fun(equal)(Cur const &pos, O const &other) ( return pos.equal(other) ) template static constexpr auto CPP_auto_fun(prev)(Cur & pos) ( return pos.prev() ) template static constexpr auto CPP_auto_fun(advance)(Cur & pos, D n) ( return pos.advance(n) ) template static constexpr auto CPP_auto_fun(distance_to)(Cur const &pos, O const &other) ( return pos.distance_to(other) ) private: template using sized_cursor_difference_t = decltype( range_access::distance_to(std::declval(), std::declval())); // clang-format on template static std::ptrdiff_t cursor_difference_2_(detail::ignore_t); template static sized_cursor_difference_t cursor_difference_2_(long); template static typename T::difference_type cursor_difference_2_(int); template using cursor_reference_t = decltype(std::declval().read()); template static meta::id>> cursor_value_2_(long); template static meta::id cursor_value_2_(int); #ifdef RANGES_WORKAROUND_CWG_1554 template struct cursor_difference { using type = decltype(range_access::cursor_difference_2_(42)); }; template struct cursor_value : decltype(range_access::cursor_value_2_(42)) {}; #endif // RANGES_WORKAROUND_CWG_1554 public: #ifdef RANGES_WORKAROUND_CWG_1554 template using cursor_difference_t = meta::_t>; template using cursor_value_t = meta::_t>; #else // ^^^ workaround ^^^ / vvv no workaround vvv template using cursor_difference_t = decltype(range_access::cursor_difference_2_(42)); template using cursor_value_t = meta::_t(42))>; #endif // RANGES_WORKAROUND_CWG_1554 template static constexpr Cur & pos(basic_iterator & it) noexcept { return it.pos(); } template static constexpr Cur const & pos(basic_iterator const & it) noexcept { return it.pos(); } template static constexpr Cur && pos(basic_iterator && it) noexcept { return detail::move(it.pos()); } template static constexpr Cur cursor(basic_iterator it) { return std::move(it.pos()); } /// endcond }; /// @} /// \cond namespace detail { // // Concepts that the range cursor must model // clang-format off // /// \concept cursor /// \brief The \c cursor concept template CPP_concept cursor = semiregular && semiregular> && constructible_from, T> && constructible_from, T const &>; // Axiom: mixin_base_t has a member get(), accessible to derived classes, // which perfectly-returns the contained cursor object and does not throw // exceptions. /// \concept has_cursor_next_ /// \brief The \c has_cursor_next_ concept template CPP_requires(has_cursor_next_, requires(T & t) ( range_access::next(t) )); /// \concept has_cursor_next /// \brief The \c has_cursor_next concept template CPP_concept has_cursor_next = CPP_requires_ref(detail::has_cursor_next_, T); /// \concept sentinel_for_cursor_ /// \brief The \c sentinel_for_cursor_ concept template CPP_requires(sentinel_for_cursor_, requires(S & s, C & c) // ( range_access::equal(c, s), concepts::requires_> )); /// \concept sentinel_for_cursor /// \brief The \c sentinel_for_cursor concept template CPP_concept sentinel_for_cursor = semiregular && cursor && CPP_requires_ref(detail::sentinel_for_cursor_, S, C); /// \concept readable_cursor_ /// \brief The \c readable_cursor_ concept template CPP_requires(readable_cursor_, requires(T & t) // ( range_access::read(t) )); /// \concept readable_cursor /// \brief The \c readable_cursor concept template CPP_concept readable_cursor = CPP_requires_ref(detail::readable_cursor_, T); /// \concept has_cursor_arrow_ /// \brief The \c has_cursor_arrow_ concept template CPP_requires(has_cursor_arrow_, requires(T const & t) // ( range_access::arrow(t) )); /// \concept has_cursor_arrow /// \brief The \c has_cursor_arrow concept template CPP_concept has_cursor_arrow = CPP_requires_ref(detail::has_cursor_arrow_, T); /// \concept writable_cursor_ /// \brief The \c writable_cursor_ concept template CPP_requires(writable_cursor_, requires(T & t, U && u) // ( range_access::write(t, (U &&) u) )); /// \concept writable_cursor /// \brief The \c writable_cursor concept template CPP_concept writable_cursor = CPP_requires_ref(detail::writable_cursor_, T, U); /// \concept sized_sentinel_for_cursor_ /// \brief The \c sized_sentinel_for_cursor_ concept template CPP_requires(sized_sentinel_for_cursor_, requires(S & s, C & c) // ( range_access::distance_to(c, s), concepts::requires_> ) ); /// \concept sized_sentinel_for_cursor /// \brief The \c sized_sentinel_for_cursor concept template CPP_concept sized_sentinel_for_cursor = sentinel_for_cursor && CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C); /// \concept output_cursor /// \brief The \c output_cursor concept template CPP_concept output_cursor = writable_cursor && cursor; /// \concept input_cursor /// \brief The \c input_cursor concept template CPP_concept input_cursor = readable_cursor && cursor && has_cursor_next; /// \concept forward_cursor /// \brief The \c forward_cursor concept template CPP_concept forward_cursor = input_cursor && sentinel_for_cursor && !range_access::single_pass_t>::value; /// \concept bidirectional_cursor_ /// \brief The \c bidirectional_cursor_ concept template CPP_requires(bidirectional_cursor_, requires(T & t) // ( range_access::prev(t) )); /// \concept bidirectional_cursor /// \brief The \c bidirectional_cursor concept template CPP_concept bidirectional_cursor = forward_cursor && CPP_requires_ref(detail::bidirectional_cursor_, T); /// \concept random_access_cursor_ /// \brief The \c random_access_cursor_ concept template CPP_requires(random_access_cursor_, requires(T & t) // ( range_access::advance(t, range_access::distance_to(t, t)) )); /// \concept random_access_cursor /// \brief The \c random_access_cursor concept template CPP_concept random_access_cursor = bidirectional_cursor && // sized_sentinel_for_cursor && // CPP_requires_ref(detail::random_access_cursor_, T); template(class T)( requires std::is_lvalue_reference::value) void is_lvalue_reference(T&&); /// \concept contiguous_cursor_ /// \brief The \c contiguous_cursor_ concept template CPP_requires(contiguous_cursor_, requires(T & t) // ( detail::is_lvalue_reference(range_access::read(t)) )); /// \concept contiguous_cursor /// \brief The \c contiguous_cursor concept template CPP_concept contiguous_cursor = random_access_cursor && // range_access::contiguous_t>::value && // CPP_requires_ref(detail::contiguous_cursor_, T); // clang-format on template RANGES_INLINE_VAR constexpr bool is_writable_cursor_ = true; template RANGES_INLINE_VAR constexpr bool is_writable_cursor_ = (bool) writable_cursor>; template RANGES_INLINE_VAR constexpr bool is_writable_cursor_v = is_writable_cursor_>; } // namespace detail /// \endcond } // namespace ranges #include #endif