Chris@16
|
1 // Boost Lambda Library ret.hpp -----------------------------------------
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //
|
Chris@16
|
9 // For more information, see www.boost.org
|
Chris@16
|
10
|
Chris@16
|
11
|
Chris@16
|
12 #ifndef BOOST_LAMBDA_RET_HPP
|
Chris@16
|
13 #define BOOST_LAMBDA_RET_HPP
|
Chris@16
|
14
|
Chris@16
|
15 namespace boost {
|
Chris@16
|
16 namespace lambda {
|
Chris@16
|
17
|
Chris@16
|
18 // TODO:
|
Chris@16
|
19
|
Chris@16
|
20 // Add specializations for function references for ret, protect and unlambda
|
Chris@16
|
21 // e.g void foo(); unlambda(foo); fails, as it would add a const qualifier
|
Chris@16
|
22 // for a function type.
|
Chris@16
|
23 // on the other hand unlambda(*foo) does work
|
Chris@16
|
24
|
Chris@16
|
25
|
Chris@16
|
26 // -- ret -------------------------
|
Chris@16
|
27 // the explicit return type template
|
Chris@16
|
28
|
Chris@16
|
29 // TODO: It'd be nice to make ret a nop for other than lambda functors
|
Chris@16
|
30 // but causes an ambiguiyty with gcc (not with KCC), check what is the
|
Chris@16
|
31 // right interpretation.
|
Chris@16
|
32
|
Chris@16
|
33 // // ret for others than lambda functors has no effect
|
Chris@16
|
34 // template <class U, class T>
|
Chris@16
|
35 // inline const T& ret(const T& t) { return t; }
|
Chris@16
|
36
|
Chris@16
|
37
|
Chris@16
|
38 template<class RET, class Arg>
|
Chris@16
|
39 inline const
|
Chris@16
|
40 lambda_functor<
|
Chris@16
|
41 lambda_functor_base<
|
Chris@16
|
42 explicit_return_type_action<RET>,
|
Chris@16
|
43 tuple<lambda_functor<Arg> >
|
Chris@16
|
44 >
|
Chris@16
|
45 >
|
Chris@16
|
46 ret(const lambda_functor<Arg>& a1)
|
Chris@16
|
47 {
|
Chris@16
|
48 return
|
Chris@16
|
49 lambda_functor_base<
|
Chris@16
|
50 explicit_return_type_action<RET>,
|
Chris@16
|
51 tuple<lambda_functor<Arg> >
|
Chris@16
|
52 >
|
Chris@16
|
53 (tuple<lambda_functor<Arg> >(a1));
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 // protect ------------------
|
Chris@16
|
57
|
Chris@16
|
58 // protecting others than lambda functors has no effect
|
Chris@16
|
59 template <class T>
|
Chris@16
|
60 inline const T& protect(const T& t) { return t; }
|
Chris@16
|
61
|
Chris@16
|
62 template<class Arg>
|
Chris@16
|
63 inline const
|
Chris@16
|
64 lambda_functor<
|
Chris@16
|
65 lambda_functor_base<
|
Chris@16
|
66 protect_action,
|
Chris@16
|
67 tuple<lambda_functor<Arg> >
|
Chris@16
|
68 >
|
Chris@16
|
69 >
|
Chris@16
|
70 protect(const lambda_functor<Arg>& a1)
|
Chris@16
|
71 {
|
Chris@16
|
72 return
|
Chris@16
|
73 lambda_functor_base<
|
Chris@16
|
74 protect_action,
|
Chris@16
|
75 tuple<lambda_functor<Arg> >
|
Chris@16
|
76 >
|
Chris@16
|
77 (tuple<lambda_functor<Arg> >(a1));
|
Chris@16
|
78 }
|
Chris@16
|
79
|
Chris@16
|
80 // -------------------------------------------------------------------
|
Chris@16
|
81
|
Chris@16
|
82 // Hides the lambda functorness of a lambda functor.
|
Chris@16
|
83 // After this, the functor is immune to argument substitution, etc.
|
Chris@16
|
84 // This can be used, e.g. to make it safe to pass lambda functors as
|
Chris@16
|
85 // arguments to functions, which might use them as target functions
|
Chris@16
|
86
|
Chris@16
|
87 // note, unlambda and protect are different things. Protect hides the lambda
|
Chris@16
|
88 // functor for one application, unlambda for good.
|
Chris@16
|
89
|
Chris@16
|
90 template <class LambdaFunctor>
|
Chris@16
|
91 class non_lambda_functor
|
Chris@16
|
92 {
|
Chris@16
|
93 LambdaFunctor lf;
|
Chris@16
|
94 public:
|
Chris@16
|
95
|
Chris@16
|
96 // This functor defines the result_type typedef.
|
Chris@16
|
97 // The result type must be deducible without knowing the arguments
|
Chris@16
|
98
|
Chris@16
|
99 template <class SigArgs> struct sig {
|
Chris@16
|
100 typedef typename
|
Chris@16
|
101 LambdaFunctor::inherited::
|
Chris@16
|
102 template sig<typename SigArgs::tail_type>::type type;
|
Chris@16
|
103 };
|
Chris@16
|
104
|
Chris@16
|
105 explicit non_lambda_functor(const LambdaFunctor& a) : lf(a) {}
|
Chris@16
|
106
|
Chris@16
|
107 typename LambdaFunctor::nullary_return_type
|
Chris@16
|
108 operator()() const {
|
Chris@16
|
109 return lf.template
|
Chris@16
|
110 call<typename LambdaFunctor::nullary_return_type>
|
Chris@16
|
111 (cnull_type(), cnull_type(), cnull_type(), cnull_type());
|
Chris@16
|
112 }
|
Chris@16
|
113
|
Chris@16
|
114 template<class A>
|
Chris@16
|
115 typename sig<tuple<const non_lambda_functor, A&> >::type
|
Chris@16
|
116 operator()(A& a) const {
|
Chris@16
|
117 return lf.template call<typename sig<tuple<const non_lambda_functor, A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
|
Chris@16
|
118 }
|
Chris@16
|
119
|
Chris@16
|
120 template<class A, class B>
|
Chris@16
|
121 typename sig<tuple<const non_lambda_functor, A&, B&> >::type
|
Chris@16
|
122 operator()(A& a, B& b) const {
|
Chris@16
|
123 return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&> >::type >(a, b, cnull_type(), cnull_type());
|
Chris@16
|
124 }
|
Chris@16
|
125
|
Chris@16
|
126 template<class A, class B, class C>
|
Chris@16
|
127 typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type
|
Chris@16
|
128 operator()(A& a, B& b, C& c) const {
|
Chris@16
|
129 return lf.template call<typename sig<tuple<const non_lambda_functor, A&, B&, C&> >::type>(a, b, c, cnull_type());
|
Chris@16
|
130 }
|
Chris@16
|
131 };
|
Chris@16
|
132
|
Chris@16
|
133 template <class Arg>
|
Chris@16
|
134 inline const Arg& unlambda(const Arg& a) { return a; }
|
Chris@16
|
135
|
Chris@16
|
136 template <class Arg>
|
Chris@16
|
137 inline const non_lambda_functor<lambda_functor<Arg> >
|
Chris@16
|
138 unlambda(const lambda_functor<Arg>& a)
|
Chris@16
|
139 {
|
Chris@16
|
140 return non_lambda_functor<lambda_functor<Arg> >(a);
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 // Due to a language restriction, lambda functors cannot be made to
|
Chris@16
|
144 // accept non-const rvalue arguments. Usually iterators do not return
|
Chris@16
|
145 // temporaries, but sometimes they do. That's why a workaround is provided.
|
Chris@16
|
146 // Note, that this potentially breaks const correctness, so be careful!
|
Chris@16
|
147
|
Chris@16
|
148 // any lambda functor can be turned into a const_incorrect_lambda_functor
|
Chris@16
|
149 // The operator() takes arguments as consts and then casts constness
|
Chris@16
|
150 // away. So this breaks const correctness!!! but is a necessary workaround
|
Chris@16
|
151 // in some cases due to language limitations.
|
Chris@16
|
152 // Note, that this is not a lambda_functor anymore, so it can not be used
|
Chris@16
|
153 // as a sub lambda expression.
|
Chris@16
|
154
|
Chris@16
|
155 template <class LambdaFunctor>
|
Chris@16
|
156 struct const_incorrect_lambda_functor {
|
Chris@16
|
157 LambdaFunctor lf;
|
Chris@16
|
158 public:
|
Chris@16
|
159
|
Chris@16
|
160 explicit const_incorrect_lambda_functor(const LambdaFunctor& a) : lf(a) {}
|
Chris@16
|
161
|
Chris@16
|
162 template <class SigArgs> struct sig {
|
Chris@16
|
163 typedef typename
|
Chris@16
|
164 LambdaFunctor::inherited::template
|
Chris@16
|
165 sig<typename SigArgs::tail_type>::type type;
|
Chris@16
|
166 };
|
Chris@16
|
167
|
Chris@16
|
168 // The nullary case is not needed (no arguments, no parameter type problems)
|
Chris@16
|
169
|
Chris@16
|
170 template<class A>
|
Chris@16
|
171 typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type
|
Chris@16
|
172 operator()(const A& a) const {
|
Chris@16
|
173 return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&> >::type >(const_cast<A&>(a), cnull_type(), cnull_type(), cnull_type());
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 template<class A, class B>
|
Chris@16
|
177 typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type
|
Chris@16
|
178 operator()(const A& a, const B& b) const {
|
Chris@16
|
179 return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&> >::type >(const_cast<A&>(a), const_cast<B&>(b), cnull_type(), cnull_type());
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182 template<class A, class B, class C>
|
Chris@16
|
183 typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type
|
Chris@16
|
184 operator()(const A& a, const B& b, const C& c) const {
|
Chris@16
|
185 return lf.template call<typename sig<tuple<const const_incorrect_lambda_functor, A&, B&, C&> >::type>(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c), cnull_type());
|
Chris@16
|
186 }
|
Chris@16
|
187 };
|
Chris@16
|
188
|
Chris@16
|
189 // ------------------------------------------------------------------------
|
Chris@16
|
190 // any lambda functor can be turned into a const_parameter_lambda_functor
|
Chris@16
|
191 // The operator() takes arguments as const.
|
Chris@16
|
192 // This is useful if lambda functors are called with non-const rvalues.
|
Chris@16
|
193 // Note, that this is not a lambda_functor anymore, so it can not be used
|
Chris@16
|
194 // as a sub lambda expression.
|
Chris@16
|
195
|
Chris@16
|
196 template <class LambdaFunctor>
|
Chris@16
|
197 struct const_parameter_lambda_functor {
|
Chris@16
|
198 LambdaFunctor lf;
|
Chris@16
|
199 public:
|
Chris@16
|
200
|
Chris@16
|
201 explicit const_parameter_lambda_functor(const LambdaFunctor& a) : lf(a) {}
|
Chris@16
|
202
|
Chris@16
|
203 template <class SigArgs> struct sig {
|
Chris@16
|
204 typedef typename
|
Chris@16
|
205 LambdaFunctor::inherited::template
|
Chris@16
|
206 sig<typename SigArgs::tail_type>::type type;
|
Chris@16
|
207 };
|
Chris@16
|
208
|
Chris@16
|
209 // The nullary case is not needed: no arguments, no constness problems.
|
Chris@16
|
210
|
Chris@16
|
211 template<class A>
|
Chris@16
|
212 typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type
|
Chris@16
|
213 operator()(const A& a) const {
|
Chris@16
|
214 return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&> >::type >(a, cnull_type(), cnull_type(), cnull_type());
|
Chris@16
|
215 }
|
Chris@16
|
216
|
Chris@16
|
217 template<class A, class B>
|
Chris@16
|
218 typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type
|
Chris@16
|
219 operator()(const A& a, const B& b) const {
|
Chris@16
|
220 return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&> >::type >(a, b, cnull_type(), cnull_type());
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@16
|
223 template<class A, class B, class C>
|
Chris@16
|
224 typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&>
|
Chris@16
|
225 >::type
|
Chris@16
|
226 operator()(const A& a, const B& b, const C& c) const {
|
Chris@16
|
227 return lf.template call<typename sig<tuple<const const_parameter_lambda_functor, const A&, const B&, const C&> >::type>(a, b, c, cnull_type());
|
Chris@16
|
228 }
|
Chris@16
|
229 };
|
Chris@16
|
230
|
Chris@16
|
231 template <class Arg>
|
Chris@16
|
232 inline const const_incorrect_lambda_functor<lambda_functor<Arg> >
|
Chris@16
|
233 break_const(const lambda_functor<Arg>& lf)
|
Chris@16
|
234 {
|
Chris@16
|
235 return const_incorrect_lambda_functor<lambda_functor<Arg> >(lf);
|
Chris@16
|
236 }
|
Chris@16
|
237
|
Chris@16
|
238
|
Chris@16
|
239 template <class Arg>
|
Chris@16
|
240 inline const const_parameter_lambda_functor<lambda_functor<Arg> >
|
Chris@16
|
241 const_parameters(const lambda_functor<Arg>& lf)
|
Chris@16
|
242 {
|
Chris@16
|
243 return const_parameter_lambda_functor<lambda_functor<Arg> >(lf);
|
Chris@16
|
244 }
|
Chris@16
|
245
|
Chris@16
|
246 // make void ------------------------------------------------
|
Chris@16
|
247 // make_void( x ) turns a lambda functor x with some return type y into
|
Chris@16
|
248 // another lambda functor, which has a void return type
|
Chris@16
|
249 // when called, the original return type is discarded
|
Chris@16
|
250
|
Chris@16
|
251 // we use this action. The action class will be called, which means that
|
Chris@16
|
252 // the wrapped lambda functor is evaluated, but we just don't do anything
|
Chris@16
|
253 // with the result.
|
Chris@16
|
254 struct voidifier_action {
|
Chris@16
|
255 template<class Ret, class A> static void apply(A&) {}
|
Chris@16
|
256 };
|
Chris@16
|
257
|
Chris@16
|
258 template<class Args> struct return_type_N<voidifier_action, Args> {
|
Chris@16
|
259 typedef void type;
|
Chris@16
|
260 };
|
Chris@16
|
261
|
Chris@16
|
262 template<class Arg1>
|
Chris@16
|
263 inline const
|
Chris@16
|
264 lambda_functor<
|
Chris@16
|
265 lambda_functor_base<
|
Chris@16
|
266 action<1, voidifier_action>,
|
Chris@16
|
267 tuple<lambda_functor<Arg1> >
|
Chris@16
|
268 >
|
Chris@16
|
269 >
|
Chris@16
|
270 make_void(const lambda_functor<Arg1>& a1) {
|
Chris@16
|
271 return
|
Chris@16
|
272 lambda_functor_base<
|
Chris@16
|
273 action<1, voidifier_action>,
|
Chris@16
|
274 tuple<lambda_functor<Arg1> >
|
Chris@16
|
275 >
|
Chris@16
|
276 (tuple<lambda_functor<Arg1> > (a1));
|
Chris@16
|
277 }
|
Chris@16
|
278
|
Chris@16
|
279 // for non-lambda functors, make_void does nothing
|
Chris@16
|
280 // (the argument gets evaluated immediately)
|
Chris@16
|
281
|
Chris@16
|
282 template<class Arg1>
|
Chris@16
|
283 inline const
|
Chris@16
|
284 lambda_functor<
|
Chris@16
|
285 lambda_functor_base<do_nothing_action, null_type>
|
Chris@16
|
286 >
|
Chris@16
|
287 make_void(const Arg1&) {
|
Chris@16
|
288 return
|
Chris@16
|
289 lambda_functor_base<do_nothing_action, null_type>();
|
Chris@16
|
290 }
|
Chris@16
|
291
|
Chris@16
|
292 // std_functor -----------------------------------------------------
|
Chris@16
|
293
|
Chris@16
|
294 // The STL uses the result_type typedef as the convention to let binders know
|
Chris@16
|
295 // the return type of a function object.
|
Chris@16
|
296 // LL uses the sig template.
|
Chris@16
|
297 // To let LL know that the function object has the result_type typedef
|
Chris@16
|
298 // defined, it can be wrapped with the std_functor function.
|
Chris@16
|
299
|
Chris@16
|
300
|
Chris@16
|
301 // Just inherit form the template parameter (the standard functor),
|
Chris@16
|
302 // and provide a sig template. So we have a class which is still the
|
Chris@16
|
303 // same functor + the sig template.
|
Chris@16
|
304
|
Chris@16
|
305 template<class T>
|
Chris@16
|
306 struct result_type_to_sig : public T {
|
Chris@16
|
307 template<class Args> struct sig { typedef typename T::result_type type; };
|
Chris@16
|
308 result_type_to_sig(const T& t) : T(t) {}
|
Chris@16
|
309 };
|
Chris@16
|
310
|
Chris@16
|
311 template<class F>
|
Chris@16
|
312 inline result_type_to_sig<F> std_functor(const F& f) { return f; }
|
Chris@16
|
313
|
Chris@16
|
314
|
Chris@16
|
315 } // namespace lambda
|
Chris@16
|
316 } // namespace boost
|
Chris@16
|
317
|
Chris@16
|
318 #endif
|
Chris@16
|
319
|
Chris@16
|
320
|
Chris@16
|
321
|
Chris@16
|
322
|
Chris@16
|
323
|
Chris@16
|
324
|
Chris@16
|
325
|