/// \file // Range v3 library // // Copyright Eric Niebler 2013-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_CONTAINER_ACTION_HPP #define RANGES_V3_CONTAINER_ACTION_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-actions /// @{ struct make_action_closure_fn { template constexpr actions::action_closure operator()(Fun fun) const { return actions::action_closure{static_cast(fun)}; } }; /// \sa make_action_closure_fn RANGES_INLINE_VARIABLE(make_action_closure_fn, make_action_closure) /// \cond namespace detail { struct action_closure_base_ {}; } /// \endcond /// \concept invocable_action_closure_ /// \brief The \c invocable_action_closure_ concept template(typename ActionFn, typename Rng)( concept (invocable_action_closure_)(ActionFn, Rng), !derived_from, detail::action_closure_base_> ); /// \concept invocable_action_closure /// \brief The \c invocable_action_closure concept template CPP_concept invocable_action_closure = invocable && CPP_concept_ref(ranges::invocable_action_closure_, ActionFn, Rng); namespace actions { struct RANGES_STRUCT_WITH_ADL_BARRIER(action_closure_base) : detail::action_closure_base_ { // clang-format off // Piping requires things are passed by value. template(typename Rng, typename ActionFn)( requires (!std::is_lvalue_reference::value) AND range AND invocable_action_closure) friend constexpr auto operator|(Rng && rng, action_closure act) { return aux::move(static_cast(act)(rng)); } #ifndef RANGES_WORKAROUND_CLANG_43400 template // ****************************** friend constexpr auto // ****************************** operator|(Rng &, // ********* READ THIS ********** action_closure const &) // ****** IF YOUR COMPILE ******* -> CPP_broken_friend_ret(Rng)( // ******** BREAKS HERE ********* requires range) = delete; // ****************************** // ************************************************************************** // * When piping a range into an action, the range must be moved in. * // ************************************************************************** #endif // RANGES_WORKAROUND_CLANG_43400 template friend constexpr auto operator|(action_closure act, Pipeable pipe) -> CPP_broken_friend_ret(action_closure>)( requires (is_pipeable_v)) { return make_action_closure(compose(static_cast(pipe), static_cast(act))); } template friend constexpr auto operator|=(Rng & rng, action_closure act) // -> CPP_broken_friend_ret(Rng &)( requires range && invocable) { static_cast(act)(rng); return rng; } // clang-format on }; #ifdef RANGES_WORKAROUND_CLANG_43400 // clang-format off namespace RANGES_ADL_BARRIER_FOR(action_closure_base) { template(typename Rng, typename ActionFn)( // ******************************* requires range) // ******************************* constexpr Rng // ********** READ THIS ********** operator|(Rng &, // ******* IF YOUR COMPILE ******* action_closure const &) // ********* BREAKS HERE ********* = delete; // ******************************* // *************************************************************************** // * When piping a range into an action, the range must be moved in. * // *************************************************************************** } // namespace RANGES_ADL_BARRIER_FOR(action_closure_base) // clang-format on #endif // RANGES_WORKAROUND_CLANG_43400 template struct RANGES_EMPTY_BASES action_closure : action_closure_base , ActionFn { action_closure() = default; constexpr explicit action_closure(ActionFn fn) : ActionFn(static_cast(fn)) {} }; /// \cond /// DEPRECATED STUFF struct action_access_ { template struct impl { // clang-format off template static constexpr auto CPP_auto_fun(bind)(Ts &&... ts) ( return A::bind(static_cast(ts)...) ) // clang-format on }; }; using action_access RANGES_DEPRECATED( "action_access and actions::action<> are deprecated. Please " "replace action<> with action_closure<> and discontinue use of " "action_access.") = action_access_; template struct old_action_; struct make_action_fn_ { template constexpr old_action_ operator()(Fun fun) const { return old_action_{static_cast(fun)}; } }; using make_action_fn RANGES_DEPRECATED( "make_action_fn is deprecated. Please use " "make_action_closure instead.") = make_action_fn_; namespace { RANGES_DEPRECATED( "make_action and actions::action<> has been deprecated. Please switch to " "make_action_closure and action::action_closure.") RANGES_INLINE_VAR constexpr auto & make_action = static_const::value; } // namespace template struct old_action_ : pipeable_base { private: Action act_; friend pipeable_access; public: old_action_() = default; constexpr explicit old_action_(Action a) noexcept( std::is_nothrow_move_constructible::value) : act_(detail::move(a)) {} // Calling directly requires things are passed by reference. template(typename Rng, typename... Rest)( requires range AND invocable) invoke_result_t // operator()(Rng & rng, Rest &&... rest) const { return invoke(act_, rng, static_cast(rest)...); } // Currying overload. // clang-format off template(typename... Rest, typename A = Action)( requires (sizeof...(Rest) != 0)) auto CPP_auto_fun(operator())(Rest &&... rest)(const) ( return make_action_fn_{}( action_access_::impl::bind(act_, static_cast(rest)...)) ) // clang-format on }; template using action RANGES_DEPRECATED( "The actions::action<> template is deprecated. Please switch to " "action_closure") = old_action_; /// \endcond } // namespace actions template RANGES_INLINE_VAR constexpr bool is_pipeable_v> = true; /// @} } // namespace ranges #include #endif