]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/mixed.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / proto / example / mixed.cpp
1 //[ Mixed
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)
6 //
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).
11
12 #include <list>
13 #include <cmath>
14 #include <vector>
15 #include <complex>
16 #include <iostream>
17 #include <stdexcept>
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;
29 using proto::_;
30
31 template<typename Expr>
32 struct MixedExpr;
33
34 template<typename Iter>
35 struct iterator_wrapper
36 {
37 typedef Iter iterator;
38
39 explicit iterator_wrapper(Iter iter)
40 : it(iter)
41 {}
42
43 mutable Iter it;
44 };
45
46 struct begin : proto::callable
47 {
48 template<class Sig>
49 struct result;
50
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>
55 >
56 {};
57
58 template<typename Cont>
59 typename result<begin(Cont const &)>::type
60 operator ()(Cont const &cont) const
61 {
62 iterator_wrapper<typename Cont::const_iterator> it(cont.begin());
63 return proto::as_expr(it);
64 }
65 };
66
67 // Here is a grammar that replaces vector and list terminals with their
68 // begin iterators
69 struct Begin
70 : proto::or_<
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> > >
75 >
76 {};
77
78 // Here is an evaluation context that dereferences iterator
79 // terminals.
80 struct DereferenceCtx
81 {
82 // Unless this is an iterator terminal, use the
83 // default evaluation context
84 template<typename Expr, typename EnableIf = void>
85 struct eval
86 : proto::default_eval<Expr, DereferenceCtx const>
87 {};
88
89 // Dereference iterator terminals.
90 template<typename Expr>
91 struct eval<
92 Expr
93 , typename boost::enable_if<
94 proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
95 >::type
96 >
97 {
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;
101
102 result_type operator ()(Expr &expr, DereferenceCtx const &) const
103 {
104 return *proto::value(expr).it;
105 }
106 };
107 };
108
109 // Here is an evaluation context that increments iterator
110 // terminals.
111 struct IncrementCtx
112 {
113 // Unless this is an iterator terminal, use the
114 // default evaluation context
115 template<typename Expr, typename EnableIf = void>
116 struct eval
117 : proto::null_eval<Expr, IncrementCtx const>
118 {};
119
120 // advance iterator terminals.
121 template<typename Expr>
122 struct eval<
123 Expr
124 , typename boost::enable_if<
125 proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
126 >::type
127 >
128 {
129 typedef void result_type;
130
131 result_type operator ()(Expr &expr, IncrementCtx const &) const
132 {
133 ++proto::value(expr).it;
134 }
135 };
136 };
137
138 // A grammar which matches all the assignment operators,
139 // so we can easily disable them.
140 struct AssignOps
141 : proto::switch_<struct AssignOpsCases>
142 {};
143
144 // Here are the cases used by the switch_ above.
145 struct AssignOpsCases
146 {
147 template<typename Tag, int D = 0> struct case_ : proto::not_<_> {};
148
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 > : _ {};
159 };
160
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.)
163 struct MixedGrammar
164 : proto::or_<
165 proto::terminal<_>
166 , proto::and_<
167 proto::nary_expr<_, proto::vararg<MixedGrammar> >
168 , proto::not_<AssignOps>
169 >
170 >
171 {};
172
173 // Expressions in the MixedDomain will be wrapped in MixedExpr<>
174 // and must conform to the MixedGrammar
175 struct MixedDomain
176 : proto::domain<proto::generator<MixedExpr>, MixedGrammar>
177 {};
178
179 // Here is MixedExpr, a wrapper for expression types in the MixedDomain.
180 template<typename Expr>
181 struct MixedExpr
182 : proto::extends<Expr, MixedExpr<Expr>, MixedDomain>
183 {
184 explicit MixedExpr(Expr const &expr)
185 : MixedExpr::proto_extends(expr)
186 {}
187 private:
188 // hide this:
189 using proto::extends<Expr, MixedExpr<Expr>, MixedDomain>::operator [];
190 };
191
192 // Define a trait type for detecting vector and list terminals, to
193 // be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
194 template<typename T>
195 struct IsMixed
196 : mpl::false_
197 {};
198
199 template<typename T, typename A>
200 struct IsMixed<std::list<T, A> >
201 : mpl::true_
202 {};
203
204 template<typename T, typename A>
205 struct IsMixed<std::vector<T, A> >
206 : mpl::true_
207 {};
208
209 namespace MixedOps
210 {
211 // This defines all the overloads to make expressions involving
212 // std::vector to build expression templates.
213 BOOST_PROTO_DEFINE_OPERATORS(IsMixed, MixedDomain)
214
215 struct assign_op
216 {
217 template<typename T, typename U>
218 void operator ()(T &t, U const &u) const
219 {
220 t = u;
221 }
222 };
223
224 struct plus_assign_op
225 {
226 template<typename T, typename U>
227 void operator ()(T &t, U const &u) const
228 {
229 t += u;
230 }
231 };
232
233 struct minus_assign_op
234 {
235 template<typename T, typename U>
236 void operator ()(T &t, U const &u) const
237 {
238 t -= u;
239 }
240 };
241
242 struct sin_
243 {
244 template<typename Sig>
245 struct result;
246
247 template<typename This, typename Arg>
248 struct result<This(Arg)>
249 : boost::remove_const<typename boost::remove_reference<Arg>::type>
250 {};
251
252 template<typename Arg>
253 Arg operator ()(Arg const &a) const
254 {
255 return std::sin(a);
256 }
257 };
258
259 template<typename A>
260 typename proto::result_of::make_expr<
261 proto::tag::function
262 , MixedDomain
263 , sin_ const
264 , A const &
265 >::type sin(A const &a)
266 {
267 return proto::make_expr<proto::tag::function, MixedDomain>(sin_(), boost::ref(a));
268 }
269
270 template<typename FwdIter, typename Expr, typename Op>
271 void evaluate(FwdIter begin, FwdIter end, Expr const &expr, Op op)
272 {
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)
277 {
278 op(*begin, proto::eval(expr2, deref));
279 proto::eval(expr2, inc);
280 }
281 }
282
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)
286 {
287 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
288 return arr;
289 }
290
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)
294 {
295 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
296 return arr;
297 }
298
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)
302 {
303 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
304 return arr;
305 }
306
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)
310 {
311 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
312 return arr;
313 }
314
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)
318 {
319 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
320 return arr;
321 }
322
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)
326 {
327 evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
328 return arr;
329 }
330 }
331
332 int main()
333 {
334 using namespace MixedOps;
335
336 int n = 10;
337 std::vector<int> a,b,c,d;
338 std::list<double> e;
339 std::list<std::complex<double> > f;
340
341 int i;
342 for(i = 0;i < n; ++i)
343 {
344 a.push_back(i);
345 b.push_back(2*i);
346 c.push_back(3*i);
347 d.push_back(i);
348 e.push_back(0.0);
349 f.push_back(std::complex<double>(1.0, 1.0));
350 }
351
352 MixedOps::assign(b, 2);
353 MixedOps::assign(d, a + b * c);
354 a += if_else(d < 30, b, c);
355
356 MixedOps::assign(e, c);
357 e += e - 4 / (c + 1);
358
359 f -= sin(0.1 * e * std::complex<double>(0.2, 1.2));
360
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)
364 {
365 std::cout
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++
372 << std::endl;
373 }
374 }
375 //]