Horizon
Loading...
Searching...
No Matches
action.hpp
Go to the documentation of this file.
1
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
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
22
31#include <range/v3/utility/static_const.hpp>
32
33#include <range/v3/detail/prologue.hpp>
34
35namespace 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
49 RANGES_INLINE_VARIABLE(make_action_closure_fn, make_action_closure)
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>
68 CPP_concept invocable_action_closure =
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
The invocable_action_closure_ concept.
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