]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/tarray.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / proto / example / tarray.cpp
1 //[ TArray
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 example constructs a mini-library for linear algebra, using
8 // expression templates to eliminate the need for temporaries when
9 // adding arrays of numbers. It duplicates the TArray example from
10 // PETE (http://www.codesourcery.com/pooma/download.html)
11
12 #include <iostream>
13 #include <boost/mpl/int.hpp>
14 #include <boost/proto/core.hpp>
15 #include <boost/proto/context.hpp>
16 namespace mpl = boost::mpl;
17 namespace proto = boost::proto;
18 using proto::_;
19
20 // This grammar describes which TArray expressions
21 // are allowed; namely, int and array terminals
22 // plus, minus, multiplies and divides of TArray expressions.
23 struct TArrayGrammar
24 : proto::or_<
25 proto::terminal< int >
26 , proto::terminal< int[3] >
27 , proto::plus< TArrayGrammar, TArrayGrammar >
28 , proto::minus< TArrayGrammar, TArrayGrammar >
29 , proto::multiplies< TArrayGrammar, TArrayGrammar >
30 , proto::divides< TArrayGrammar, TArrayGrammar >
31 >
32 {};
33
34 template<typename Expr>
35 struct TArrayExpr;
36
37 // Tell proto that in the TArrayDomain, all
38 // expressions should be wrapped in TArrayExpr<> and
39 // must conform to the TArrayGrammar
40 struct TArrayDomain
41 : proto::domain<proto::generator<TArrayExpr>, TArrayGrammar>
42 {};
43
44 // Here is an evaluation context that indexes into a TArray
45 // expression, and combines the result.
46 struct TArraySubscriptCtx
47 : proto::callable_context< TArraySubscriptCtx const >
48 {
49 typedef int result_type;
50
51 TArraySubscriptCtx(std::ptrdiff_t i)
52 : i_(i)
53 {}
54
55 // Index array terminals with our subscript. Everything
56 // else will be handled by the default evaluation context.
57 int operator ()(proto::tag::terminal, int const (&data)[3]) const
58 {
59 return data[this->i_];
60 }
61
62 std::ptrdiff_t i_;
63 };
64
65 // Here is an evaluation context that prints a TArray expression.
66 struct TArrayPrintCtx
67 : proto::callable_context< TArrayPrintCtx const >
68 {
69 typedef std::ostream &result_type;
70
71 TArrayPrintCtx() {}
72
73 std::ostream &operator ()(proto::tag::terminal, int i) const
74 {
75 return std::cout << i;
76 }
77
78 std::ostream &operator ()(proto::tag::terminal, int const (&arr)[3]) const
79 {
80 return std::cout << '{' << arr[0] << ", " << arr[1] << ", " << arr[2] << '}';
81 }
82
83 template<typename L, typename R>
84 std::ostream &operator ()(proto::tag::plus, L const &l, R const &r) const
85 {
86 return std::cout << '(' << l << " + " << r << ')';
87 }
88
89 template<typename L, typename R>
90 std::ostream &operator ()(proto::tag::minus, L const &l, R const &r) const
91 {
92 return std::cout << '(' << l << " - " << r << ')';
93 }
94
95 template<typename L, typename R>
96 std::ostream &operator ()(proto::tag::multiplies, L const &l, R const &r) const
97 {
98 return std::cout << l << " * " << r;
99 }
100
101 template<typename L, typename R>
102 std::ostream &operator ()(proto::tag::divides, L const &l, R const &r) const
103 {
104 return std::cout << l << " / " << r;
105 }
106 };
107
108 // Here is the domain-specific expression wrapper, which overrides
109 // operator [] to evaluate the expression using the TArraySubscriptCtx.
110 template<typename Expr>
111 struct TArrayExpr
112 : proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain>
113 {
114 typedef proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain> base_type;
115
116 TArrayExpr( Expr const & expr = Expr() )
117 : base_type( expr )
118 {}
119
120 // Use the TArraySubscriptCtx to implement subscripting
121 // of a TArray expression tree.
122 int operator []( std::ptrdiff_t i ) const
123 {
124 TArraySubscriptCtx const ctx(i);
125 return proto::eval(*this, ctx);
126 }
127
128 // Use the TArrayPrintCtx to display a TArray expression tree.
129 friend std::ostream &operator <<(std::ostream &sout, TArrayExpr<Expr> const &expr)
130 {
131 TArrayPrintCtx const ctx;
132 return proto::eval(expr, ctx);
133 }
134 };
135
136 // Here is our TArray terminal, implemented in terms of TArrayExpr
137 // It is basically just an array of 3 integers.
138 struct TArray
139 : TArrayExpr< proto::terminal< int[3] >::type >
140 {
141 explicit TArray( int i = 0, int j = 0, int k = 0 )
142 {
143 (*this)[0] = i;
144 (*this)[1] = j;
145 (*this)[2] = k;
146 }
147
148 // Here we override operator [] to give read/write access to
149 // the elements of the array. (We could use the TArrayExpr
150 // operator [] if we made the subscript context smarter about
151 // returning non-const reference when appropriate.)
152 int &operator [](std::ptrdiff_t i)
153 {
154 return proto::value(*this)[i];
155 }
156
157 int const &operator [](std::ptrdiff_t i) const
158 {
159 return proto::value(*this)[i];
160 }
161
162 // Here we define a operator = for TArray terminals that
163 // takes a TArray expression.
164 template< typename Expr >
165 TArray &operator =(Expr const & expr)
166 {
167 // proto::as_expr<TArrayDomain>(expr) is the same as
168 // expr unless expr is an integer, in which case it
169 // is made into a TArrayExpr terminal first.
170 return this->assign(proto::as_expr<TArrayDomain>(expr));
171 }
172
173 template< typename Expr >
174 TArray &printAssign(Expr const & expr)
175 {
176 *this = expr;
177 std::cout << *this << " = " << expr << std::endl;
178 return *this;
179 }
180
181 private:
182 template< typename Expr >
183 TArray &assign(Expr const & expr)
184 {
185 // expr[i] here uses TArraySubscriptCtx under the covers.
186 (*this)[0] = expr[0];
187 (*this)[1] = expr[1];
188 (*this)[2] = expr[2];
189 return *this;
190 }
191 };
192
193 int main()
194 {
195 TArray a(3,1,2);
196
197 TArray b;
198
199 std::cout << a << std::endl;
200 std::cout << b << std::endl;
201
202 b[0] = 7; b[1] = 33; b[2] = -99;
203
204 TArray c(a);
205
206 std::cout << c << std::endl;
207
208 a = 0;
209
210 std::cout << a << std::endl;
211 std::cout << b << std::endl;
212 std::cout << c << std::endl;
213
214 a = b + c;
215
216 std::cout << a << std::endl;
217
218 a.printAssign(b+c*(b + 3*c));
219
220 return 0;
221 }
222 //]