]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/mini_lambda.cpp
2 ///////////////////////////////////////////////////////////////////////////////
3 // Copyright 2008 Eric Niebler. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // This example builds a simple but functional lambda library using Proto.
11 #include <boost/mpl/int.hpp>
12 #include <boost/mpl/min_max.hpp>
13 #include <boost/mpl/eval_if.hpp>
14 #include <boost/mpl/identity.hpp>
15 #include <boost/mpl/next_prior.hpp>
16 #include <boost/fusion/tuple.hpp>
17 #include <boost/typeof/typeof.hpp>
18 #include <boost/typeof/std/ostream.hpp>
19 #include <boost/typeof/std/iostream.hpp>
20 #include <boost/proto/core.hpp>
21 #include <boost/proto/context.hpp>
22 #include <boost/proto/transform.hpp>
23 namespace mpl
= boost::mpl
;
24 namespace proto
= boost::proto
;
25 namespace fusion
= boost::fusion
;
28 // Forward declaration of the lambda expression wrapper
33 : proto::domain
<proto::pod_generator
<lambda
> >
43 struct placeholder_arity
45 typedef typename
T::arity type
;
48 // The lambda grammar, with the transforms for calculating the max arity
52 proto::terminal
< placeholder
<_
> >
53 , mpl::next
<placeholder_arity
<proto::_value
> >()
55 , proto::when
< proto::terminal
<_
>
59 proto::nary_expr
<_
, proto::vararg
<_
> >
60 , proto::fold
<_
, mpl::int_
<0>(), mpl::max
<lambda_arity
, proto::_state
>()>
65 // The lambda context is the same as the default context
66 // with the addition of special handling for lambda placeholders
67 template<typename Tuple
>
69 : proto::callable_context
<lambda_context
<Tuple
> const>
71 lambda_context(Tuple
const &args
)
75 template<typename Sig
>
78 template<typename This
, typename I
>
79 struct result
<This(proto::tag::terminal
, placeholder
<I
> const &)>
80 : fusion::result_of::at
<Tuple
, I
>
84 typename
fusion::result_of::at
<Tuple
, I
>::type
85 operator ()(proto::tag::terminal
, placeholder
<I
> const &) const
87 return fusion::at
<I
>(this->args_
);
93 // The lambda<> expression wrapper makes expressions polymorphic
98 BOOST_PROTO_BASIC_EXTENDS(T
, lambda
<T
>, lambda_domain
)
99 BOOST_PROTO_EXTENDS_ASSIGN()
100 BOOST_PROTO_EXTENDS_SUBSCRIPT()
102 // Calculate the arity of this lambda expression
103 static int const arity
= boost::result_of
<lambda_arity(T
)>::type::value
;
105 template<typename Sig
>
108 // Define nested result<> specializations to calculate the return
109 // type of this lambda expression. But be careful not to evaluate
110 // the return type of the nullary function unless we have a nullary
112 template<typename This
>
113 struct result
<This()>
116 , proto::result_of::eval
<T
const, lambda_context
<fusion::tuple
<> > >
117 , mpl::identity
<void>
121 template<typename This
, typename A0
>
122 struct result
<This(A0
)>
123 : proto::result_of::eval
<T
const, lambda_context
<fusion::tuple
<A0
> > >
126 template<typename This
, typename A0
, typename A1
>
127 struct result
<This(A0
, A1
)>
128 : proto::result_of::eval
<T
const, lambda_context
<fusion::tuple
<A0
, A1
> > >
131 // Define our operator () that evaluates the lambda expression.
132 typename result
<lambda()>::type
135 fusion::tuple
<> args
;
136 lambda_context
<fusion::tuple
<> > ctx(args
);
137 return proto::eval(*this, ctx
);
140 template<typename A0
>
141 typename result
<lambda(A0
const &)>::type
142 operator ()(A0
const &a0
) const
144 fusion::tuple
<A0
const &> args(a0
);
145 lambda_context
<fusion::tuple
<A0
const &> > ctx(args
);
146 return proto::eval(*this, ctx
);
149 template<typename A0
, typename A1
>
150 typename result
<lambda(A0
const &, A1
const &)>::type
151 operator ()(A0
const &a0
, A1
const &a1
) const
153 fusion::tuple
<A0
const &, A1
const &> args(a0
, a1
);
154 lambda_context
<fusion::tuple
<A0
const &, A1
const &> > ctx(args
);
155 return proto::eval(*this, ctx
);
159 // Define some lambda placeholders
160 lambda
<proto::terminal
<placeholder
<mpl::int_
<0> > >::type
> const _1
= {{}};
161 lambda
<proto::terminal
<placeholder
<mpl::int_
<1> > >::type
> const _2
= {{}};
164 lambda
<typename
proto::terminal
<T
>::type
> const val(T
const &t
)
166 lambda
<typename
proto::terminal
<T
>::type
> that
= {{t
}};
171 lambda
<typename
proto::terminal
<T
&>::type
> const var(T
&t
)
173 lambda
<typename
proto::terminal
<T
&>::type
> that
= {{t
}};
178 struct construct_helper
180 typedef T result_type
; // for TR1 result_of
185 // Generate BOOST_PROTO_MAX_ARITY overloads of the
186 // following function call operator.
187 #define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, a)\
188 template<typename_A(N)> \
189 T operator()(A_const_ref_a(N)) const \
191 #define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
192 #include BOOST_PROTO_LOCAL_ITERATE()
195 // Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
196 // following construct() function template.
197 #define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
198 template<typename T, typename_A(N)> \
199 typename proto::result_of::make_expr< \
200 proto::tag::function \
202 , construct_helper<T> \
205 construct(A_const_ref_a(N)) \
207 return proto::make_expr< \
208 proto::tag::function \
211 construct_helper<T>() \
215 BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY
, M0
)
223 std::cout
<< "S(" << i
<< "," << c
<< ")\n";
229 // Create some lambda objects and immediately
230 // invoke them by applying their operator():
231 int i
= ( (_1
+ 2) / 4 )(42);
232 std::cout
<< i
<< std::endl
; // prints 11
234 int j
= ( (-(_1
+ 2)) / 4 )(42);
235 std::cout
<< j
<< std::endl
; // prints -11
237 double d
= ( (4 - _2
) * 3 )(42, 3.14);
238 std::cout
<< d
<< std::endl
; // prints 2.58
240 // check non-const ref terminals
241 (std::cout
<< _1
<< " -- " << _2
<< '\n')(42, "Life, the Universe and Everything!");
242 // prints "42 -- Life, the Universe and Everything!"
244 // "Nullary" lambdas work too
245 int k
= (val(1) + val(2))();
246 std::cout
<< k
<< std::endl
; // prints 3
248 // check array indexing for kicks
249 int integers
[5] = {0};
250 (var(integers
)[2] = 2)();
251 (var(integers
)[_1
] = _1
)(3);
252 std::cout
<< integers
[2] << std::endl
; // prints 2
253 std::cout
<< integers
[3] << std::endl
; // prints 3
255 // Now use a lambda with an STL algorithm!
256 int rgi
[4] = {1,2,3,4};
257 char rgc
[4] = {'a','b','c','d'};
260 std::transform(rgi
, rgi
+4, rgc
, rgs
, construct
<S
>(_1
, _2
));