]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/mixed.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 is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
8 // expressions using std::vector<> and std::list, non-proto types. It is a port
9 // of the Mixed example from PETE.
10 // (http://www.codesourcery.com/pooma/download.html).
18 #include <boost/proto/core.hpp>
19 #include <boost/proto/debug.hpp>
20 #include <boost/proto/context.hpp>
21 #include <boost/proto/transform.hpp>
22 #include <boost/utility/enable_if.hpp>
23 #include <boost/typeof/std/list.hpp>
24 #include <boost/typeof/std/vector.hpp>
25 #include <boost/typeof/std/complex.hpp>
26 #include <boost/type_traits/remove_reference.hpp>
27 namespace proto
= boost::proto
;
28 namespace mpl
= boost::mpl
;
31 template<typename Expr
>
34 template<typename Iter
>
35 struct iterator_wrapper
37 typedef Iter iterator
;
39 explicit iterator_wrapper(Iter iter
)
46 struct begin
: proto::callable
51 template<class This
, class Cont
>
52 struct result
<This(Cont
)>
53 : proto::result_of::as_expr
<
54 iterator_wrapper
<typename
boost::remove_reference
<Cont
>::type::const_iterator
>
58 template<typename Cont
>
59 typename result
<begin(Cont
const &)>::type
60 operator ()(Cont
const &cont
) const
62 iterator_wrapper
<typename
Cont::const_iterator
> it(cont
.begin());
63 return proto::as_expr(it
);
67 // Here is a grammar that replaces vector and list terminals with their
71 proto::when
< proto::terminal
< std::vector
<_
, _
> >, begin(proto::_value
) >
72 , proto::when
< proto::terminal
< std::list
<_
, _
> >, begin(proto::_value
) >
73 , proto::when
< proto::terminal
<_
> >
74 , proto::when
< proto::nary_expr
<_
, proto::vararg
<Begin
> > >
78 // Here is an evaluation context that dereferences iterator
82 // Unless this is an iterator terminal, use the
83 // default evaluation context
84 template<typename Expr
, typename EnableIf
= void>
86 : proto::default_eval
<Expr
, DereferenceCtx
const>
89 // Dereference iterator terminals.
90 template<typename Expr
>
93 , typename
boost::enable_if
<
94 proto::matches
<Expr
, proto::terminal
<iterator_wrapper
<_
> > >
98 typedef typename
proto::result_of::value
<Expr
>::type IteratorWrapper
;
99 typedef typename
IteratorWrapper::iterator iterator
;
100 typedef typename
std::iterator_traits
<iterator
>::reference result_type
;
102 result_type
operator ()(Expr
&expr
, DereferenceCtx
const &) const
104 return *proto::value(expr
).it
;
109 // Here is an evaluation context that increments iterator
113 // Unless this is an iterator terminal, use the
114 // default evaluation context
115 template<typename Expr
, typename EnableIf
= void>
117 : proto::null_eval
<Expr
, IncrementCtx
const>
120 // advance iterator terminals.
121 template<typename Expr
>
124 , typename
boost::enable_if
<
125 proto::matches
<Expr
, proto::terminal
<iterator_wrapper
<_
> > >
129 typedef void result_type
;
131 result_type
operator ()(Expr
&expr
, IncrementCtx
const &) const
133 ++proto::value(expr
).it
;
138 // A grammar which matches all the assignment operators,
139 // so we can easily disable them.
141 : proto::switch_
<struct AssignOpsCases
>
144 // Here are the cases used by the switch_ above.
145 struct AssignOpsCases
147 template<typename Tag
, int D
= 0> struct case_
: proto::not_
<_
> {};
149 template<int D
> struct case_
< proto::tag::plus_assign
, D
> : _
{};
150 template<int D
> struct case_
< proto::tag::minus_assign
, D
> : _
{};
151 template<int D
> struct case_
< proto::tag::multiplies_assign
, D
> : _
{};
152 template<int D
> struct case_
< proto::tag::divides_assign
, D
> : _
{};
153 template<int D
> struct case_
< proto::tag::modulus_assign
, D
> : _
{};
154 template<int D
> struct case_
< proto::tag::shift_left_assign
, D
> : _
{};
155 template<int D
> struct case_
< proto::tag::shift_right_assign
, D
> : _
{};
156 template<int D
> struct case_
< proto::tag::bitwise_and_assign
, D
> : _
{};
157 template<int D
> struct case_
< proto::tag::bitwise_or_assign
, D
> : _
{};
158 template<int D
> struct case_
< proto::tag::bitwise_xor_assign
, D
> : _
{};
161 // An expression conforms to the MixedGrammar if it is a terminal or some
162 // op that is not an assignment op. (Assignment will be handled specially.)
167 proto::nary_expr
<_
, proto::vararg
<MixedGrammar
> >
168 , proto::not_
<AssignOps
>
173 // Expressions in the MixedDomain will be wrapped in MixedExpr<>
174 // and must conform to the MixedGrammar
176 : proto::domain
<proto::generator
<MixedExpr
>, MixedGrammar
>
179 // Here is MixedExpr, a wrapper for expression types in the MixedDomain.
180 template<typename Expr
>
182 : proto::extends
<Expr
, MixedExpr
<Expr
>, MixedDomain
>
184 explicit MixedExpr(Expr
const &expr
)
185 : MixedExpr::proto_extends(expr
)
189 using proto::extends
<Expr
, MixedExpr
<Expr
>, MixedDomain
>::operator [];
192 // Define a trait type for detecting vector and list terminals, to
193 // be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
199 template<typename T
, typename A
>
200 struct IsMixed
<std::list
<T
, A
> >
204 template<typename T
, typename A
>
205 struct IsMixed
<std::vector
<T
, A
> >
211 // This defines all the overloads to make expressions involving
212 // std::vector to build expression templates.
213 BOOST_PROTO_DEFINE_OPERATORS(IsMixed
, MixedDomain
)
217 template<typename T
, typename U
>
218 void operator ()(T
&t
, U
const &u
) const
224 struct plus_assign_op
226 template<typename T
, typename U
>
227 void operator ()(T
&t
, U
const &u
) const
233 struct minus_assign_op
235 template<typename T
, typename U
>
236 void operator ()(T
&t
, U
const &u
) const
244 template<typename Sig
>
247 template<typename This
, typename Arg
>
248 struct result
<This(Arg
)>
249 : boost::remove_const
<typename
boost::remove_reference
<Arg
>::type
>
252 template<typename Arg
>
253 Arg
operator ()(Arg
const &a
) const
260 typename
proto::result_of::make_expr
<
265 >::type
sin(A
const &a
)
267 return proto::make_expr
<proto::tag::function
, MixedDomain
>(sin_(), boost::ref(a
));
270 template<typename FwdIter
, typename Expr
, typename Op
>
271 void evaluate(FwdIter begin
, FwdIter end
, Expr
const &expr
, Op op
)
273 IncrementCtx
const inc
= {};
274 DereferenceCtx
const deref
= {};
275 typename
boost::result_of
<Begin(Expr
const &)>::type expr2
= Begin()(expr
);
276 for(; begin
!= end
; ++begin
)
278 op(*begin
, proto::eval(expr2
, deref
));
279 proto::eval(expr2
, inc
);
283 // Add-assign to a vector from some expression.
284 template<typename T
, typename A
, typename Expr
>
285 std::vector
<T
, A
> &assign(std::vector
<T
, A
> &arr
, Expr
const &expr
)
287 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), assign_op());
291 // Add-assign to a list from some expression.
292 template<typename T
, typename A
, typename Expr
>
293 std::list
<T
, A
> &assign(std::list
<T
, A
> &arr
, Expr
const &expr
)
295 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), assign_op());
299 // Add-assign to a vector from some expression.
300 template<typename T
, typename A
, typename Expr
>
301 std::vector
<T
, A
> &operator +=(std::vector
<T
, A
> &arr
, Expr
const &expr
)
303 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), plus_assign_op());
307 // Add-assign to a list from some expression.
308 template<typename T
, typename A
, typename Expr
>
309 std::list
<T
, A
> &operator +=(std::list
<T
, A
> &arr
, Expr
const &expr
)
311 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), plus_assign_op());
315 // Minus-assign to a vector from some expression.
316 template<typename T
, typename A
, typename Expr
>
317 std::vector
<T
, A
> &operator -=(std::vector
<T
, A
> &arr
, Expr
const &expr
)
319 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), minus_assign_op());
323 // Minus-assign to a list from some expression.
324 template<typename T
, typename A
, typename Expr
>
325 std::list
<T
, A
> &operator -=(std::list
<T
, A
> &arr
, Expr
const &expr
)
327 evaluate(arr
.begin(), arr
.end(), proto::as_expr
<MixedDomain
>(expr
), minus_assign_op());
334 using namespace MixedOps
;
337 std::vector
<int> a
,b
,c
,d
;
339 std::list
<std::complex<double> > f
;
342 for(i
= 0;i
< n
; ++i
)
349 f
.push_back(std::complex<double>(1.0, 1.0));
352 MixedOps::assign(b
, 2);
353 MixedOps::assign(d
, a
+ b
* c
);
354 a
+= if_else(d
< 30, b
, c
);
356 MixedOps::assign(e
, c
);
357 e
+= e
- 4 / (c
+ 1);
359 f
-= sin(0.1 * e
* std::complex<double>(0.2, 1.2));
361 std::list
<double>::const_iterator ei
= e
.begin();
362 std::list
<std::complex<double> >::const_iterator fi
= f
.begin();
363 for (i
= 0; i
< n
; ++i
)
366 << "a(" << i
<< ") = " << a
[i
]
367 << " b(" << i
<< ") = " << b
[i
]
368 << " c(" << i
<< ") = " << c
[i
]
369 << " d(" << i
<< ") = " << d
[i
]
370 << " e(" << i
<< ") = " << *ei
++
371 << " f(" << i
<< ") = " << *fi
++