1 | // Boost Lambda Library ret.hpp ----------------------------------------- |
2 | |
3 | // Copyright (C) 1999, 2000 Jaakko Jarvi (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&) { |
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 | |
326 | |