]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/phoenix/include/boost/phoenix/function/lazy_reuse.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / phoenix / include / boost / phoenix / function / lazy_reuse.hpp
CommitLineData
7c673cae
FG
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
40namespace 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.
56struct INV {};
57struct VAR {};
58
59template <class V, class X> struct Maybe_Var_Inv;
60template <class X>
61struct 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};
68template <class X>
69struct 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
78template <class Result>
79class ThunkImpl
80{
81 mutable RefCountType refC;
82public:
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
92template <class T>
93void intrusive_ptr_add_ref( const ThunkImpl<T>* p ) {
94 ++ (p->refC);
95}
96template <class T>
97void 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
105template <class V1, class V2, class F, class X>
106struct reuser1;
107
108template <class V1, class V2, class F, class X, class R>
109struct 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
124template <class V1, class V2, class F, class X>
125struct 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
147template <class V1, class V2, class V3, class F, class X, class Y>
148struct reuser2;
149
150template <class V1, class V2, class V3, class F, class X, class Y, class R>
151struct 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
169template <class V1, class V2, class V3, class F, class X, class Y>
170struct 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
191template <class V1, class V2, class V3, class V4,
192 class F, class X, class Y, class Z>
193struct reuser3;
194
195template <class V1, class V2, class V3, class V4,
196 class F, class X, class Y, class Z, class R>
197struct 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
219template <class V1, class V2, class V3, class V4,
220 class F, class X, class Y, class Z>
221struct 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>
243struct 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>
247struct 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