action.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_CONTAINER_ACTION_HPP
  14. #define RANGES_V3_CONTAINER_ACTION_HPP
  15. #include <type_traits>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/action/concepts.hpp>
  19. #include <range/v3/functional/compose.hpp>
  20. #include <range/v3/functional/concepts.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/functional/reference_wrapper.hpp>
  23. #include <range/v3/functional/pipeable.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. #include <range/v3/utility/move.hpp>
  26. #include <range/v3/utility/static_const.hpp>
  27. #include <range/v3/detail/prologue.hpp>
  28. namespace ranges
  29. {
  30. /// \addtogroup group-actions
  31. /// @{
  32. struct make_action_closure_fn
  33. {
  34. template<typename Fun>
  35. constexpr actions::action_closure<Fun> operator()(Fun fun) const
  36. {
  37. return actions::action_closure<Fun>{static_cast<Fun &&>(fun)};
  38. }
  39. };
  40. /// \sa make_action_closure_fn
  41. RANGES_INLINE_VARIABLE(make_action_closure_fn, make_action_closure)
  42. /// \cond
  43. namespace detail
  44. {
  45. struct action_closure_base_
  46. {};
  47. }
  48. /// \endcond
  49. /// \concept invocable_action_closure_
  50. /// \brief The \c invocable_action_closure_ concept
  51. template(typename ActionFn, typename Rng)(
  52. concept (invocable_action_closure_)(ActionFn, Rng),
  53. !derived_from<invoke_result_t<ActionFn, Rng>, detail::action_closure_base_>
  54. );
  55. /// \concept invocable_action_closure
  56. /// \brief The \c invocable_action_closure concept
  57. template<typename ActionFn, typename Rng>
  58. CPP_concept invocable_action_closure =
  59. invocable<ActionFn, Rng> &&
  60. CPP_concept_ref(ranges::invocable_action_closure_, ActionFn, Rng);
  61. namespace actions
  62. {
  63. struct RANGES_STRUCT_WITH_ADL_BARRIER(action_closure_base)
  64. : detail::action_closure_base_
  65. {
  66. // clang-format off
  67. // Piping requires things are passed by value.
  68. template(typename Rng, typename ActionFn)(
  69. requires (!std::is_lvalue_reference<Rng>::value) AND
  70. range<Rng> AND invocable_action_closure<ActionFn, Rng &>)
  71. friend constexpr auto
  72. operator|(Rng && rng, action_closure<ActionFn> act)
  73. {
  74. return aux::move(static_cast<ActionFn &&>(act)(rng));
  75. }
  76. #ifndef RANGES_WORKAROUND_CLANG_43400
  77. template<typename Rng, typename ActionFn> // ******************************
  78. friend constexpr auto // ******************************
  79. operator|(Rng &, // ********* READ THIS **********
  80. action_closure<ActionFn> const &) // ****** IF YOUR COMPILE *******
  81. -> CPP_broken_friend_ret(Rng)( // ******** BREAKS HERE *********
  82. requires range<Rng>) = delete; // ******************************
  83. // **************************************************************************
  84. // * When piping a range into an action, the range must be moved in. *
  85. // **************************************************************************
  86. #endif // RANGES_WORKAROUND_CLANG_43400
  87. template<typename ActionFn, typename Pipeable>
  88. friend constexpr auto operator|(action_closure<ActionFn> act, Pipeable pipe)
  89. -> CPP_broken_friend_ret(action_closure<composed<Pipeable, ActionFn>>)(
  90. requires (is_pipeable_v<Pipeable>))
  91. {
  92. return make_action_closure(compose(static_cast<Pipeable &&>(pipe),
  93. static_cast<ActionFn &&>(act)));
  94. }
  95. template<typename Rng, typename ActionFn>
  96. friend constexpr auto operator|=(Rng & rng, action_closure<ActionFn> act) //
  97. -> CPP_broken_friend_ret(Rng &)(
  98. requires range<Rng> && invocable<ActionFn, Rng &>)
  99. {
  100. static_cast<ActionFn &&>(act)(rng);
  101. return rng;
  102. }
  103. // clang-format on
  104. };
  105. #ifdef RANGES_WORKAROUND_CLANG_43400
  106. // clang-format off
  107. namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
  108. {
  109. template(typename Rng, typename ActionFn)( // *******************************
  110. requires range<Rng>) // *******************************
  111. constexpr Rng // ********** READ THIS **********
  112. operator|(Rng &, // ******* IF YOUR COMPILE *******
  113. action_closure<ActionFn> const &) // ********* BREAKS HERE *********
  114. = delete; // *******************************
  115. // ***************************************************************************
  116. // * When piping a range into an action, the range must be moved in. *
  117. // ***************************************************************************
  118. } // namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
  119. // clang-format on
  120. #endif // RANGES_WORKAROUND_CLANG_43400
  121. template<typename ActionFn>
  122. struct RANGES_EMPTY_BASES action_closure
  123. : action_closure_base
  124. , ActionFn
  125. {
  126. action_closure() = default;
  127. constexpr explicit action_closure(ActionFn fn)
  128. : ActionFn(static_cast<ActionFn &&>(fn))
  129. {}
  130. };
  131. /// \cond
  132. /// DEPRECATED STUFF
  133. struct action_access_
  134. {
  135. template<typename Action>
  136. struct impl
  137. {
  138. // clang-format off
  139. template<typename... Ts, typename A = Action>
  140. static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
  141. (
  142. return A::bind(static_cast<Ts &&>(ts)...)
  143. )
  144. // clang-format on
  145. };
  146. };
  147. using action_access RANGES_DEPRECATED(
  148. "action_access and actions::action<> are deprecated. Please "
  149. "replace action<> with action_closure<> and discontinue use of "
  150. "action_access.") = action_access_;
  151. template<typename>
  152. struct old_action_;
  153. struct make_action_fn_
  154. {
  155. template<typename Fun>
  156. constexpr old_action_<Fun> operator()(Fun fun) const
  157. {
  158. return old_action_<Fun>{static_cast<Fun &&>(fun)};
  159. }
  160. };
  161. using make_action_fn RANGES_DEPRECATED(
  162. "make_action_fn is deprecated. Please use "
  163. "make_action_closure instead.") = make_action_fn_;
  164. namespace
  165. {
  166. RANGES_DEPRECATED(
  167. "make_action and actions::action<> has been deprecated. Please switch to "
  168. "make_action_closure and action::action_closure.")
  169. RANGES_INLINE_VAR constexpr auto & make_action =
  170. static_const<make_action_fn_>::value;
  171. } // namespace
  172. template<typename Action>
  173. struct old_action_ : pipeable_base
  174. {
  175. private:
  176. Action act_;
  177. friend pipeable_access;
  178. public:
  179. old_action_() = default;
  180. constexpr explicit old_action_(Action a) noexcept(
  181. std::is_nothrow_move_constructible<Action>::value)
  182. : act_(detail::move(a))
  183. {}
  184. // Calling directly requires things are passed by reference.
  185. template(typename Rng, typename... Rest)(
  186. requires range<Rng> AND invocable<Action const &, Rng &, Rest...>)
  187. invoke_result_t<Action const &, Rng &, Rest...> //
  188. operator()(Rng & rng, Rest &&... rest) const
  189. {
  190. return invoke(act_, rng, static_cast<Rest &&>(rest)...);
  191. }
  192. // Currying overload.
  193. // clang-format off
  194. template(typename... Rest, typename A = Action)(
  195. requires (sizeof...(Rest) != 0))
  196. auto CPP_auto_fun(operator())(Rest &&... rest)(const)
  197. (
  198. return make_action_fn_{}(
  199. action_access_::impl<A>::bind(act_,
  200. static_cast<Rest &&>(rest)...))
  201. )
  202. // clang-format on
  203. };
  204. template<typename Action>
  205. using action RANGES_DEPRECATED(
  206. "The actions::action<> template is deprecated. Please switch to "
  207. "action_closure") = old_action_<Action>;
  208. /// \endcond
  209. } // namespace actions
  210. template<typename ActionFn>
  211. RANGES_INLINE_VAR constexpr bool is_pipeable_v<actions::action_closure<ActionFn>> =
  212. true;
  213. /// @}
  214. } // namespace ranges
  215. #include <range/v3/detail/epilogue.hpp>
  216. #endif