Horizon
action.hpp
Go to the documentation of this file.
1 // 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 
14 #ifndef RANGES_V3_CONTAINER_ACTION_HPP
15 #define RANGES_V3_CONTAINER_ACTION_HPP
16 
17 #include <type_traits>
18 
19 #include <meta/meta.hpp>
20 
21 #include <range/v3/range_fwd.hpp>
22 
31 #include <range/v3/utility/static_const.hpp>
32 
33 #include <range/v3/detail/prologue.hpp>
34 
35 namespace ranges
36 {
40  {
41  template<typename Fun>
42  constexpr actions::action_closure<Fun> operator()(Fun fun) const
43  {
44  return actions::action_closure<Fun>{static_cast<Fun &&>(fun)};
45  }
46  };
47 
50 
51 
52  namespace detail
53  {
54  struct action_closure_base_
55  {};
56  }
58 
61  template(typename ActionFn, typename Rng)(
62  concept (invocable_action_closure_)(ActionFn, Rng),
63  !derived_from<invoke_result_t<ActionFn, Rng>, detail::action_closure_base_>
64  );
67  template<typename ActionFn, typename Rng>
69  invocable<ActionFn, Rng> &&
70  CPP_concept_ref(ranges::invocable_action_closure_, ActionFn, Rng);
71 
72  namespace actions
73  {
74  struct RANGES_STRUCT_WITH_ADL_BARRIER(action_closure_base)
75  : detail::action_closure_base_
76  {
77  // clang-format off
78  // Piping requires things are passed by value.
79  template(typename Rng, typename ActionFn)(
80  requires (!std::is_lvalue_reference<Rng>::value) AND
81  range<Rng> AND invocable_action_closure<ActionFn, Rng &>)
82  friend constexpr auto
83  operator|(Rng && rng, action_closure<ActionFn> act)
84  {
85  return aux::move(static_cast<ActionFn &&>(act)(rng));
86  }
87 
88 #ifndef RANGES_WORKAROUND_CLANG_43400
89  template<typename Rng, typename ActionFn> // ******************************
90  friend constexpr auto // ******************************
91  operator|(Rng &, // ********* READ THIS **********
92  action_closure<ActionFn> const &) // ****** IF YOUR COMPILE *******
93  -> CPP_broken_friend_ret(Rng)( // ******** BREAKS HERE *********
94  requires range<Rng>) = delete; // ******************************
95  // **************************************************************************
96  // * When piping a range into an action, the range must be moved in. *
97  // **************************************************************************
98 #endif // RANGES_WORKAROUND_CLANG_43400
99 
100  template<typename ActionFn, typename Pipeable>
101  friend constexpr auto operator|(action_closure<ActionFn> act, Pipeable pipe)
102  -> CPP_broken_friend_ret(action_closure<composed<Pipeable, ActionFn>>)(
103  requires (is_pipeable_v<Pipeable>))
104  {
105  return make_action_closure(compose(static_cast<Pipeable &&>(pipe),
106  static_cast<ActionFn &&>(act)));
107  }
108 
109  template<typename Rng, typename ActionFn>
110  friend constexpr auto operator|=(Rng & rng, action_closure<ActionFn> act) //
111  -> CPP_broken_friend_ret(Rng &)(
112  requires range<Rng> && invocable<ActionFn, Rng &>)
113  {
114  static_cast<ActionFn &&>(act)(rng);
115  return rng;
116  }
117  // clang-format on
118  };
119 
120 #ifdef RANGES_WORKAROUND_CLANG_43400
121  // clang-format off
122  namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
123  {
124  template(typename Rng, typename ActionFn)( // *******************************
125  requires range<Rng>) // *******************************
126  constexpr Rng // ********** READ THIS **********
127  operator|(Rng &, // ******* IF YOUR COMPILE *******
128  action_closure<ActionFn> const &) // ********* BREAKS HERE *********
129  = delete; // *******************************
130  // ***************************************************************************
131  // * When piping a range into an action, the range must be moved in. *
132  // ***************************************************************************
133  } // namespace RANGES_ADL_BARRIER_FOR(action_closure_base)
134  // clang-format on
135 #endif // RANGES_WORKAROUND_CLANG_43400
136 
137  template<typename ActionFn>
138  struct RANGES_EMPTY_BASES action_closure
139  : action_closure_base
140  , ActionFn
141  {
142  action_closure() = default;
143 
144  constexpr explicit action_closure(ActionFn fn)
145  : ActionFn(static_cast<ActionFn &&>(fn))
146  {}
147  };
148 
151  struct action_access_
152  {
153  template<typename Action>
154  struct impl
155  {
156  // clang-format off
157  template<typename... Ts, typename A = Action>
158  static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
159  (
160  return A::bind(static_cast<Ts &&>(ts)...)
161  )
162  // clang-format on
163  };
164  };
165 
166  using action_access RANGES_DEPRECATED(
167  "action_access and actions::action<> are deprecated. Please "
168  "replace action<> with action_closure<> and discontinue use of "
169  "action_access.") = action_access_;
170 
171  template<typename>
172  struct old_action_;
173 
174  struct make_action_fn_
175  {
176  template<typename Fun>
177  constexpr old_action_<Fun> operator()(Fun fun) const
178  {
179  return old_action_<Fun>{static_cast<Fun &&>(fun)};
180  }
181  };
182  using make_action_fn RANGES_DEPRECATED(
183  "make_action_fn is deprecated. Please use "
184  "make_action_closure instead.") = make_action_fn_;
185 
186  namespace
187  {
188  RANGES_DEPRECATED(
189  "make_action and actions::action<> has been deprecated. Please switch to "
190  "make_action_closure and action::action_closure.")
191  RANGES_INLINE_VAR constexpr auto & make_action =
192  static_const<make_action_fn_>::value;
193  } // namespace
194 
195  template<typename Action>
196  struct old_action_ : pipeable_base
197  {
198  private:
199  Action act_;
200  friend pipeable_access;
201 
202  public:
203  old_action_() = default;
204 
205  constexpr explicit old_action_(Action a) noexcept(
206  std::is_nothrow_move_constructible<Action>::value)
207  : act_(detail::move(a))
208  {}
209 
210  // Calling directly requires things are passed by reference.
211  template(typename Rng, typename... Rest)(
212  requires range<Rng> AND invocable<Action const &, Rng &, Rest...>)
213  invoke_result_t<Action const &, Rng &, Rest...> //
214  operator()(Rng & rng, Rest &&... rest) const
215  {
216  return invoke(act_, rng, static_cast<Rest &&>(rest)...);
217  }
218 
219  // Currying overload.
220  // clang-format off
221  template(typename... Rest, typename A = Action)(
222  requires (sizeof...(Rest) != 0))
223  auto CPP_auto_fun(operator())(Rest &&... rest)(const)
224  (
225  return make_action_fn_{}(
226  action_access_::impl<A>::bind(act_,
227  static_cast<Rest &&>(rest)...))
228  )
229  // clang-format on
230  };
231 
232  template<typename Action>
233  using action RANGES_DEPRECATED(
234  "The actions::action<> template is deprecated. Please switch to "
235  "action_closure") = old_action_<Action>;
237  } // namespace actions
238 
239  template<typename ActionFn>
240  RANGES_INLINE_VAR constexpr bool is_pipeable_v<actions::action_closure<ActionFn>> =
241  true;
243 } // namespace ranges
244 
245 #include <range/v3/detail/epilogue.hpp>
246 
247 #endif
CPP_concept invocable_action_closure
\concept invocable_action_closure
Definition: action.hpp:68
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
Tiny meta-programming library.
Definition: action.hpp:141
Definition: action.hpp:40