]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/phoenix/include/boost/phoenix/function/lazy_reuse.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / phoenix / include / boost / phoenix / function / lazy_reuse.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 // lazy_reuse.hpp
3 //
4 // Build lazy operations for Phoenix equivalents for FC++
5 //
6 // These are equivalents of the Boost FC++ functoids in reuse.hpp
7 //
8 // Implemented so far:
9 //
10 // reuser1
11 // reuser2
12 // reuser3
13 // reuser4 (not yet tested)
14 //
15 // NOTE: It has been possible to simplify the operation of this code.
16 // It now makes no use of boost::function or old FC++ code.
17 //
18 // The functor type F must be an operator defined with
19 // boost::phoenix::function.
20 // See the example Apply in lazy_prelude.hpp
21 //
22 ////////////////////////////////////////////////////////////////////////////
23 /*=============================================================================
24 Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
25 Copyright (c) 2001-2007 Joel de Guzman
26 Copyright (c) 2015 John Fletcher
27
28 Distributed under the Boost Software License, Version 1.0. (See accompanying
29 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
30 ==============================================================================*/
31
32 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_REUSE
33 #define BOOST_PHOENIX_FUNCTION_LAZY_REUSE
34
35 #include <boost/phoenix/core.hpp>
36 #include <boost/phoenix/function.hpp>
37 #include <boost/intrusive_ptr.hpp>
38
39
40 namespace boost {
41
42 namespace phoenix {
43
44 namespace fcpp {
45
46 //////////////////////////////////////////////////////////////////////
47 // Original FC++ comment:
48 // "Reuser"s are effectively special-purpose versions of curry() that
49 // enable recursive list functoids to reuse the thunk of the curried
50 // recursive call. See
51 // http://www.cc.gatech.edu/~yannis/fc++/New/reusers.html
52 // for a more detailed description.
53 //////////////////////////////////////////////////////////////////////
54
55 // For efficiency, we mark parameters as either "VAR"iant or "INV"ariant.
56 struct INV {};
57 struct VAR {};
58
59 template <class V, class X> struct Maybe_Var_Inv;
60 template <class X>
61 struct Maybe_Var_Inv<VAR,X> {
62 static void remake( X& x, const X& val ) {
63 x.~X();
64 new (&x) X(val);
65 }
66 static X clone( const X& x ) { return X(x); }
67 };
68 template <class X>
69 struct Maybe_Var_Inv<INV,X> {
70 static void remake( X&, const X& ) {}
71 static const X& clone( const X& x ) { return x; }
72 };
73
74 /////////////////////////////////////////////////////////////////////
75 // ThunkImpl is an implementation of Fun0Impl for this use.
76 /////////////////////////////////////////////////////////////////////
77
78 template <class Result>
79 class ThunkImpl
80 {
81 mutable RefCountType refC;
82 public:
83 ThunkImpl() : refC(0) {}
84 virtual Result operator()() const =0;
85 virtual ~ThunkImpl() {}
86 template <class X>
87 friend void intrusive_ptr_add_ref( const ThunkImpl<X>* p );
88 template <class X>
89 friend void intrusive_ptr_release( const ThunkImpl<X>* p );
90 };
91
92 template <class T>
93 void intrusive_ptr_add_ref( const ThunkImpl<T>* p ) {
94 ++ (p->refC);
95 }
96 template <class T>
97 void intrusive_ptr_release( const ThunkImpl<T>* p ) {
98 if( !--(p->refC) ) delete p;
99 }
100
101 //////////////////////////////////////////////////////////////////////
102 // reuser1 is needed in list<T> operations
103 //////////////////////////////////////////////////////////////////////
104
105 template <class V1, class V2, class F, class X>
106 struct reuser1;
107
108 template <class V1, class V2, class F, class X, class R>
109 struct Thunk1 : public ThunkImpl<R> {
110 mutable F f;
111 mutable X x;
112 Thunk1( const F& ff, const X& xx ) : f(ff), x(xx) {}
113 void init( const F& ff, const X& xx ) const {
114 Maybe_Var_Inv<V1,F>::remake( f, ff );
115 Maybe_Var_Inv<V2,X>::remake( x, xx );
116 }
117 R operator()() const {
118 return Maybe_Var_Inv<V1,F>::clone(f)(
119 Maybe_Var_Inv<V2,X>::clone(x),
120 reuser1<V1,V2,F,X>(this) );
121 }
122 };
123
124 template <class V1, class V2, class F, class X>
125 struct reuser1 {
126 typedef typename F::template result<F(X)>::type R;
127 typedef typename boost::phoenix::function<R> fun0_type;
128 typedef Thunk1<V1,V2,F,X,R> M;
129 typedef M result_type;
130 boost::intrusive_ptr<const M> ref;
131 reuser1(a_unique_type_for_nil) {}
132 reuser1(const M* m) : ref(m) {}
133 M operator()( const F& f, const X& x ) {
134 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x) );
135 else ref->init(f,x);
136 return *ref;
137 }
138 void iter( const F& f, const X& x ) {
139 if( ref ) ref->init(f,x);
140 }
141 };
142
143 //////////////////////////////////////////////////////////////////////
144 // reuser2 is needed in list<T>
145 //////////////////////////////////////////////////////////////////////
146
147 template <class V1, class V2, class V3, class F, class X, class Y>
148 struct reuser2;
149
150 template <class V1, class V2, class V3, class F, class X, class Y, class R>
151 struct Thunk2 : public ThunkImpl<R> {
152 mutable F f;
153 mutable X x;
154 mutable Y y;
155 Thunk2( const F& ff, const X& xx, const Y& yy ) : f(ff), x(xx), y(yy) {}
156 void init( const F& ff, const X& xx, const Y& yy ) const {
157 Maybe_Var_Inv<V1,F>::remake( f, ff );
158 Maybe_Var_Inv<V2,X>::remake( x, xx );
159 Maybe_Var_Inv<V3,Y>::remake( y, yy );
160 }
161 R operator()() const {
162 return Maybe_Var_Inv<V1,F>::clone(f)(
163 Maybe_Var_Inv<V2,X>::clone(x),
164 Maybe_Var_Inv<V3,Y>::clone(y),
165 reuser2<V1,V2,V3,F,X,Y>(this) );
166 }
167 };
168
169 template <class V1, class V2, class V3, class F, class X, class Y>
170 struct reuser2 {
171 typedef typename F::template result<F(X,Y)>::type R;
172 typedef Thunk2<V1,V2,V3,F,X,Y,R> M;
173 typedef M result_type;
174 boost::intrusive_ptr<const M> ref;
175 reuser2(a_unique_type_for_nil) {}
176 reuser2(const M* m) : ref(m) {}
177 M operator()( const F& f, const X& x, const Y& y ) {
178 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y) );
179 else ref->init(f,x,y);
180 return *ref;
181 }
182 void iter( const F& f, const X& x, const Y& y ) {
183 if( ref ) ref->init(f,x,y);
184 }
185 };
186
187 //////////////////////////////////////////////////////////////////////
188 // reuser3
189 //////////////////////////////////////////////////////////////////////
190
191 template <class V1, class V2, class V3, class V4,
192 class F, class X, class Y, class Z>
193 struct reuser3;
194
195 template <class V1, class V2, class V3, class V4,
196 class F, class X, class Y, class Z, class R>
197 struct Thunk3 : public ThunkImpl<R> {
198 mutable F f;
199 mutable X x;
200 mutable Y y;
201 mutable Z z;
202 Thunk3( const F& ff, const X& xx, const Y& yy, const Z& zz )
203 : f(ff), x(xx), y(yy), z(zz) {}
204 void init( const F& ff, const X& xx, const Y& yy, const Z& zz ) const {
205 Maybe_Var_Inv<V1,F>::remake( f, ff );
206 Maybe_Var_Inv<V2,X>::remake( x, xx );
207 Maybe_Var_Inv<V3,Y>::remake( y, yy );
208 Maybe_Var_Inv<V4,Z>::remake( z, zz );
209 }
210 R operator()() const {
211 return Maybe_Var_Inv<V1,F>::clone(f)(
212 Maybe_Var_Inv<V2,X>::clone(x),
213 Maybe_Var_Inv<V3,Y>::clone(y),
214 Maybe_Var_Inv<V4,Z>::clone(z),
215 reuser3<V1,V2,V3,V4,F,X,Y,Z>(this) );
216 }
217 };
218
219 template <class V1, class V2, class V3, class V4,
220 class F, class X, class Y, class Z>
221 struct reuser3 {
222 typedef typename F::template result<F(X,Y,Z)>::type R;
223 typedef Thunk3<V1,V2,V3,V4,F,X,Y,Z,R> M;
224 typedef M result_type;
225 boost::intrusive_ptr<const M> ref;
226 reuser3(a_unique_type_for_nil) {}
227 reuser3(const M* m) : ref(m) {}
228 M operator()( const F& f, const X& x, const Y& y, const Z& z ) {
229 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y,z) );
230 else ref->init(f,x,y,z);
231 return *ref;
232 }
233 void iter( const F& f, const X& x, const Y& y, const Z& z ) {
234 if( ref ) ref->init(f,x,y,z);
235 }
236 };
237 //////////////////////////////////////////////////////////////////////
238 // reuser4
239 //////////////////////////////////////////////////////////////////////
240
241 template <class V1, class V2, class V3, class V4, class V5,
242 class F, class W, class X, class Y, class Z>
243 struct reuser4;
244
245 template <class V1, class V2, class V3, class V4, class V5,
246 class F, class W, class X, class Y, class Z, class R>
247 struct Thunk4 : public ThunkImpl<R> {
248 mutable F f;
249 mutable W w;
250 mutable X x;
251 mutable Y y;
252 mutable Z z;
253 Thunk4( const F& ff, const W& ww, const X& xx, const Y& yy, const Z& zz )
254 : f(ff), w(ww), x(xx), y(yy), z(zz) {}
255 void init( const F& ff, const W& ww, const X& xx, const Y& yy, const Z& zz ) const {
256 Maybe_Var_Inv<V1,F>::remake( f, ff );
257 Maybe_Var_Inv<V2,W>::remake( w, ww );
258 Maybe_Var_Inv<V3,X>::remake( x, xx );
259 Maybe_Var_Inv<V4,Y>::remake( y, yy );
260 Maybe_Var_Inv<V5,Z>::remake( z, zz );
261 }
262 R operator()() const {
263 return Maybe_Var_Inv<V1,F>::clone(f)(
264 Maybe_Var_Inv<V2,W>::clone(w),
265 Maybe_Var_Inv<V3,X>::clone(x),
266 Maybe_Var_Inv<V4,Y>::clone(y),
267 Maybe_Var_Inv<V5,Z>::clone(z),
268 reuser4<V1,V2,V3,V4,V5,F,W,X,Y,Z>(this) );
269 }
270 };
271
272 template <class V1, class V2, class V3, class V4, class V5,
273 class F, class W, class X, class Y, class Z>
274 struct reuser4 {
275 typedef typename F::template result<F(W,X,Y,Z)>::type R;
276 typedef Thunk4<V1,V2,V3,V4,V5,F,W,X,Y,Z,R> M;
277 typedef M result_type;
278 boost::intrusive_ptr<const M> ref;
279 reuser4(a_unique_type_for_nil) {}
280 reuser4(const M* m) : ref(m) {}
281 M operator()( const F& f, const W& w, const X& x, const Y& y, const Z& z ) {
282 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,w,x,y,z) );
283 else ref->init(f,w,x,y,z);
284 return *ref;
285 }
286 void iter( const F& f, const W& w, const X& x, const Y& y, const Z& z ) {
287 if( ref ) ref->init(f,w,x,y,z);
288 }
289 };
290
291 }
292
293 }
294 }
295
296 #endif