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