/// \file // Range v3 library // // Copyright Eric Niebler 2014-present // // 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_VIEW_FACADE_HPP #define RANGES_V3_VIEW_FACADE_HPP #include #include #include #include #include #include #include #include #include namespace ranges { /// \cond namespace detail { template using begin_cursor_t = detail::decay_t()))>; template using end_cursor_t = detail::decay_t()))>; template using facade_iterator_t = basic_iterator>; template using facade_sentinel_t = meta::if_c, end_cursor_t>, facade_iterator_t, end_cursor_t>; } // namespace detail /// \endcond /// \addtogroup group-views /// @{ /// \brief A utility for constructing a view from a (derived) type that /// implements begin and end cursors. /// \tparam Derived A type that derives from `view_facade` and implements /// begin and end cursors. This type is permitted to be incomplete. /// \tparam Cardinality The cardinality of this view: `finite`, `infinite`, /// or `unknown`. See `ranges::cardinality`. template struct view_facade : view_interface { protected: friend range_access; using view_interface::derived; struct view_as_cursor : Derived { view_as_cursor() = default; explicit view_as_cursor(Derived const * derived) : Derived(*derived) {} explicit operator bool() = delete; explicit operator bool() const = delete; }; // Default implementations constexpr view_as_cursor begin_cursor() const { return view_as_cursor{&derived()}; } constexpr default_sentinel_t end_cursor() const { return {}; } public: /// Let `d` be `static_cast(*this)`. Let `b` be /// `std::as_const(d).begin_cursor()` if that expression is well-formed; /// otherwise, let `b` be `d.begin_cursor()`. Let `B` be the type of /// `b`. /// \return `ranges::basic_iterator(b)` template constexpr auto begin() -> CPP_ret(detail::facade_iterator_t)( // requires same_as) { return detail::facade_iterator_t{range_access::begin_cursor(derived())}; } /// \overload template constexpr auto begin() const -> CPP_ret(detail::facade_iterator_t)( // requires same_as) { return detail::facade_iterator_t{ range_access::begin_cursor(derived())}; } /// Let `d` be `static_cast(*this)`. Let `e` be /// `std::as_const(d).end_cursor()` if that expression is well-formed; /// otherwise, let `e` be `d.end_cursor()`. Let `E` be the type of /// `e`. /// \return `ranges::basic_iterator(e)` if `E` is the same /// as `B` computed above for `begin()`; otherwise, return `e`. template constexpr auto end() -> CPP_ret(detail::facade_sentinel_t)( // requires same_as) { return static_cast>( range_access::end_cursor(derived())); } /// \overload template constexpr auto end() const -> CPP_ret(detail::facade_sentinel_t)( // requires same_as) { return static_cast>( range_access::end_cursor(derived())); } }; /// @} } // namespace ranges #endif