/// \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_VIEW_HPP #define RANGES_V3_VIEW_VIEW_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-views /// @{ /// \cond namespace detail { struct dereference_fn { // clang-format off template constexpr auto CPP_auto_fun(operator())(I &&i) (const) ( return *(I &&) i ) // clang-format on }; struct view_closure_base_ {}; } // namespace detail /// \endcond // clang-format off /// \concept simple_view_impl_ /// \brief The \c simple_view_impl_ concept template(typename Rng)( concept (simple_view_impl_)(Rng), same_as, iterator_t> AND same_as, sentinel_t>); /// \concept simple_view_ /// \brief The \c simple_view_ concept template CPP_concept simple_view_ = view_ && range && CPP_concept_ref(ranges::simple_view_impl_, Rng); /// \concept invocable_view_closure_ /// \brief The \c invocable_view_closure_ concept template(typename ViewFn, typename Rng)( concept (invocable_view_closure_)(ViewFn, Rng), !derived_from, detail::view_closure_base_>); /// \concept invocable_view_closure /// \brief The \c invocable_view_closure concept template CPP_concept invocable_view_closure = invocable && CPP_concept_ref(ranges::invocable_view_closure_, ViewFn, Rng); // clang-format on template constexpr bool simple_view() noexcept { return (bool)simple_view_; } struct make_view_closure_fn { template constexpr views::view_closure operator()(Fun fun) const { return views::view_closure{static_cast(fun)}; } }; /// \ingroup group-views /// \sa make_view_closure_fn RANGES_INLINE_VARIABLE(make_view_closure_fn, make_view_closure) namespace views { struct RANGES_STRUCT_WITH_ADL_BARRIER(view_closure_base) : detail::view_closure_base_ { // Piping requires viewable_ranges. Pipeing a value into a closure // should not yield another closure. template(typename Rng, typename ViewFn)( requires viewable_range AND invocable_view_closure) friend constexpr auto operator|(Rng && rng, view_closure vw) { return static_cast(vw)(static_cast(rng)); } #ifndef RANGES_WORKAROUND_CLANG_43400 // This overload is deleted because when piping a range into an // view, it must be moved in. template // ************************** friend constexpr auto // ************************** operator|(Rng &&, view_closure const &) // ******* READ THIS ******** // **** IF YOUR COMPILE ***** -> CPP_broken_friend_ret(Rng)( // ****** BREAKS HERE ******* requires range && // ************************** (!viewable_range)) = delete; // ************************** // ************************************************************************** // * When piping a range into an adaptor, the range must satisfy the * // * "viewable_range" concept. A range is viewable when either or both * // * of these things are true: * // * - The range is an lvalue (not a temporary object), OR * // * - The range is a view (not a container). * // ************************************************************************** #endif template friend constexpr auto operator|(view_closure vw, Pipeable pipe) -> CPP_broken_friend_ret(view_closure>)( requires (is_pipeable_v)) { return make_view_closure( compose(static_cast(pipe), static_cast(vw))); } }; #ifdef RANGES_WORKAROUND_CLANG_43400 namespace RANGES_ADL_BARRIER_FOR(view_closure_base) { // This overload is deleted because when piping a range into an // view, it must be moved in. template(typename Rng, typename ViewFn)( // ************************ requires range AND (!viewable_range))// ************************ constexpr Rng // ************************ operator|(Rng &&, view_closure const &) // ****** READ THIS ******* = delete; // *** IF YOUR COMPILE **** // ***** BREAKS HERE ****** // ************************ // ************************ // *************************************************************************** // * When piping a range into an adaptor, the range must satisfy the * // * "viewable_range" concept. A range is viewable when either or both * // * of these things are true: * // * - The range is an lvalue (not a temporary object), OR * // * - The range is a view (not a container). * // *************************************************************************** } // namespace ) #endif // RANGES_WORKAROUND_CLANG_43400 template struct RANGES_EMPTY_BASES view_closure : view_closure_base , ViewFn { view_closure() = default; constexpr explicit view_closure(ViewFn fn) : ViewFn(static_cast(fn)) {} }; /// \cond /// DEPRECATED STUFF struct view_access_ { template struct impl { // clang-format off template static constexpr auto CPP_auto_fun(bind)(Ts &&... ts) ( return V::bind(static_cast(ts)...) ) // clang-format on }; }; using view_access RANGES_DEPRECATED( "view_access and views::view<> are deprecated. Please " "replace view<> with view_closure<> and discontinue use of view_access.") = view_access_; template struct old_view_; struct make_view_fn_ { template constexpr old_view_ operator()(Fun fun) const { return old_view_{static_cast(fun)}; } }; using make_view_fn RANGES_DEPRECATED( "make_view_fn is deprecated. Please use " "make_view_closure instead.") = make_view_fn_; namespace { RANGES_DEPRECATED( "make_view and views::view<> has been deprecated. Please switch to " "make_view_closure and views::view_closure.") RANGES_INLINE_VAR constexpr auto & make_view = static_const::value; } // namespace template struct old_view_ : pipeable_base { private: ViewFn vw_; friend pipeable_access; // Piping requires range arguments or lvalue containers. template(typename Rng, typename Vw)( requires viewable_range AND invocable) static constexpr auto pipe(Rng && rng, Vw && v) { return v.vw_(static_cast(rng)); } public: old_view_() = default; constexpr explicit old_view_(ViewFn a) noexcept( std::is_nothrow_move_constructible::value) : vw_(std::move(a)) {} // Calling directly requires a viewable_range. template(typename Rng, typename... Rest)( requires viewable_range AND invocable) constexpr invoke_result_t // operator()(Rng && rng, Rest &&... rest) const { return vw_(static_cast(rng), static_cast(rest)...); } // Currying overload. // clang-format off template constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const) ( return make_view_fn_{}( view_access_::impl::bind(vw_, static_cast(ts)...)) ) // clang-format on }; template using view RANGES_DEPRECATED( "The views::view<> template is deprecated. Please switch to view_closure") = old_view_; /// \endcond } // namespace views template RANGES_INLINE_VAR constexpr bool is_pipeable_v> = true; /// @} } // namespace ranges #include #endif