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