/// \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 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 // CPP_def ( template(typename T) 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. ); CPP_def ( template(typename T) concept has_cursor_next, requires (T &t) ( range_access::next(t) ) ); CPP_def ( template(typename S, typename C) concept sentinel_for_cursor, requires (S &s, C &c) ( range_access::equal(c, s), concepts::requires_> ) && semiregular && cursor ); CPP_def ( template(typename T) concept readable_cursor, requires (T &t) ( range_access::read(t) ) ); CPP_def ( template(typename T) concept has_cursor_arrow, requires (T const &t) ( range_access::arrow(t) ) ); CPP_def ( template(typename T, typename U) concept writable_cursor, requires (T &t, U &&u) ( range_access::write(t, (U &&) u) ) ); CPP_def ( template(typename S, typename C) concept sized_sentinel_for_cursor, requires (S &s, C &c) ( range_access::distance_to(c, s), concepts::requires_> ) && sentinel_for_cursor ); CPP_def ( template(typename T, typename U) concept output_cursor, writable_cursor && cursor ); CPP_def ( template(typename T) concept input_cursor, readable_cursor && cursor && has_cursor_next ); CPP_def ( template(typename T) concept forward_cursor, input_cursor && sentinel_for_cursor && !range_access::single_pass_t>::value ); CPP_def ( template(typename T) concept bidirectional_cursor, requires (T &t) ( range_access::prev(t) ) && forward_cursor ); CPP_def ( template(typename T) concept random_access_cursor, requires (T &t) ( range_access::advance(t, range_access::distance_to(t, t)) ) && bidirectional_cursor && sized_sentinel_for_cursor ); CPP_def ( template(typename T) concept contiguous_cursor, requires (T &t) ( concepts::requires_::value> ) && random_access_cursor && range_access::contiguous_t>::value ); // clang-format on using cursor_tag = concepts::tag; using input_cursor_tag = concepts::tag; using forward_cursor_tag = concepts::tag; using bidirectional_cursor_tag = concepts::tag; using random_access_cursor_tag = concepts::tag; using contiguous_cursor_tag = concepts::tag; template using cursor_tag_of = concepts::tag_of, T>; template struct is_writable_cursor_ : std::true_type {}; template struct is_writable_cursor_ : meta::bool_<(bool)writable_cursor>> {}; template struct is_writable_cursor : detail::is_writable_cursor_> {}; } // namespace detail /// \endcond } // namespace ranges #endif