]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/test/lambda.cpp
1 ///////////////////////////////////////////////////////////////////////////////
4 // Copyright 2008 Eric Niebler. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 #include <boost/mpl/int.hpp>
10 #include <boost/mpl/min_max.hpp>
11 #include <boost/mpl/eval_if.hpp>
12 #include <boost/mpl/identity.hpp>
13 #include <boost/mpl/next_prior.hpp>
14 #include <boost/fusion/tuple.hpp>
15 #include <boost/typeof/typeof.hpp>
16 #include <boost/typeof/std/sstream.hpp>
17 #include <boost/typeof/std/ostream.hpp>
18 #include <boost/typeof/std/iostream.hpp>
19 #include <boost/type_traits/add_const.hpp>
20 #include <boost/type_traits/add_reference.hpp>
21 #include <boost/proto/core.hpp>
22 #include <boost/proto/context.hpp>
23 #include <boost/proto/transform.hpp>
24 #include <boost/test/unit_test.hpp>
25 #include <boost/test/floating_point_comparison.hpp>
27 using namespace boost
;
29 // Forward declaration of the lambda expression wrapper
34 : proto::domain
<proto::pod_generator
<lambda
> >
44 struct placeholder_arity
46 typedef typename
T::arity type
;
51 using namespace proto
;
53 // The lambda grammar, with the transforms for calculating the max arity
56 when
< terminal
< placeholder
<_
> >, mpl::next
<placeholder_arity
<_value
> >() >
57 , when
< terminal
<_
>, mpl::int_
<0>() >
58 , when
< nary_expr
<_
, vararg
<_
> >, fold
<_
, mpl::int_
<0>(), mpl::max
<Lambda
,_state
>()> >
63 // simple wrapper for calculating a lambda expression's arity.
64 template<typename Expr
>
66 : boost::result_of
<grammar::Lambda(Expr
, mpl::void_
, mpl::void_
)>
69 // The lambda context is the same as the default context
70 // with the addition of special handling for lambda placeholders
71 template<typename Tuple
>
73 : proto::callable_context
<lambda_context
<Tuple
> const>
75 lambda_context(Tuple
const &args
)
79 template<typename Sig
>
82 template<typename This
, typename I
>
83 struct result
<This(proto::tag::terminal
, placeholder
<I
> const &)>
84 : fusion::result_of::at
<Tuple
, I
>
88 typename
fusion::result_of::at
<Tuple
, I
>::type
89 operator ()(proto::tag::terminal
, placeholder
<I
> const &) const
91 return fusion::at
<I
>(this->args_
);
97 // The lambda<> expression wrapper makes expressions polymorphic
102 BOOST_PROTO_BASIC_EXTENDS(T
, lambda
<T
>, lambda_domain
)
103 BOOST_PROTO_EXTENDS_ASSIGN()
104 BOOST_PROTO_EXTENDS_SUBSCRIPT()
106 // Careful not to evaluate the return type of the nullary function
107 // unless we have a nullary lambda!
108 typedef typename
mpl::eval_if
<
109 typename lambda_arity
<T
>::type
110 , mpl::identity
<void>
111 , proto::result_of::eval
<T
const, lambda_context
<fusion::tuple
<> > >
112 >::type nullary_type
;
114 // Define our operator () that evaluates the lambda expression.
115 nullary_type
operator ()() const
117 fusion::tuple
<> args
;
118 lambda_context
<fusion::tuple
<> > ctx(args
);
119 return proto::eval(*this, ctx
);
122 #define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
123 template<typename_A(N)> \
124 typename proto::result_of::eval<T const, lambda_context<fusion::tuple<A_const_ref(N)> > >::type \
125 operator ()(A_const_ref_a(N)) const \
127 fusion::tuple<A_const_ref(N)> args(ref_a(N)); \
128 lambda_context<fusion::tuple<A_const_ref(N)> > ctx(args); \
129 return proto::eval(*this, ctx); \
132 BOOST_PROTO_REPEAT_FROM_TO(1, 4, M0
)
136 // Define some lambda placeholders
137 lambda
<proto::terminal
<placeholder
<mpl::int_
<0> > >::type
> const _1
= {{}};
138 lambda
<proto::terminal
<placeholder
<mpl::int_
<1> > >::type
> const _2
= {{}};
139 lambda
<proto::terminal
<placeholder
<mpl::int_
<3> > >::type
> const _3
= {{}};
142 lambda
<typename
proto::terminal
<T
>::type
> const val(T
const &t
)
144 lambda
<typename
proto::terminal
<T
>::type
> that
= {{t
}};
149 lambda
<typename
proto::terminal
<T
&>::type
> const var(T
&t
)
151 lambda
<typename
proto::terminal
<T
&>::type
> that
= {{t
}};
157 BOOST_CHECK_EQUAL(11, ( (_1
+ 2) / 4 )(42));
158 BOOST_CHECK_EQUAL(-11, ( (-(_1
+ 2)) / 4 )(42));
159 BOOST_CHECK_CLOSE(2.58, ( (4 - _2
) * 3 )(42, 3.14), 0.1);
161 // check non-const ref terminals
162 std::stringstream sout
;
163 (sout
<< _1
<< " -- " << _2
)(42, "Life, the Universe and Everything!");
164 BOOST_CHECK_EQUAL("42 -- Life, the Universe and Everything!", sout
.str());
166 // check nullary lambdas
167 BOOST_CHECK_EQUAL(3, (val(1) + val(2))());
169 // check array indexing for kicks
170 int integers
[5] = {0};
171 (var(integers
)[2] = 2)();
172 (var(integers
)[_1
] = _1
)(3);
173 BOOST_CHECK_EQUAL(2, integers
[2]);
174 BOOST_CHECK_EQUAL(3, integers
[3]);
177 using namespace unit_test
;
178 ///////////////////////////////////////////////////////////////////////////////
179 // init_unit_test_suite
181 test_suite
* init_unit_test_suite( int argc
, char* argv
[] )
183 test_suite
*test
= BOOST_TEST_SUITE("test expression template domains");
185 test
->add(BOOST_TEST_CASE(&test_lambda
));