Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 /// \file extends.hpp
|
Chris@16
|
3 /// Macros and a base class for defining end-user expression types
|
Chris@16
|
4 //
|
Chris@16
|
5 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
6 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_PROTO_EXTENDS_HPP_EAN_11_1_2006
|
Chris@16
|
10 #define BOOST_PROTO_EXTENDS_HPP_EAN_11_1_2006
|
Chris@16
|
11
|
Chris@16
|
12 #include <cstddef> // for offsetof
|
Chris@16
|
13 #include <boost/config.hpp>
|
Chris@16
|
14 #include <boost/detail/workaround.hpp>
|
Chris@16
|
15 #include <boost/preprocessor/facilities/empty.hpp>
|
Chris@16
|
16 #include <boost/preprocessor/tuple/elem.hpp>
|
Chris@16
|
17 #include <boost/preprocessor/control/if.hpp>
|
Chris@16
|
18 #include <boost/preprocessor/arithmetic/inc.hpp>
|
Chris@16
|
19 #include <boost/preprocessor/arithmetic/dec.hpp>
|
Chris@16
|
20 #include <boost/preprocessor/iteration/local.hpp>
|
Chris@16
|
21 #include <boost/preprocessor/repetition/enum_params.hpp>
|
Chris@16
|
22 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
Chris@16
|
23 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
Chris@16
|
24 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
Chris@16
|
25 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
|
Chris@16
|
26 #include <boost/preprocessor/seq/for_each.hpp>
|
Chris@16
|
27 #include <boost/utility/addressof.hpp>
|
Chris@16
|
28 #include <boost/utility/result_of.hpp>
|
Chris@16
|
29 #include <boost/proto/proto_fwd.hpp>
|
Chris@16
|
30 #include <boost/proto/traits.hpp>
|
Chris@16
|
31 #include <boost/proto/expr.hpp>
|
Chris@16
|
32 #include <boost/proto/args.hpp>
|
Chris@16
|
33 #include <boost/proto/traits.hpp>
|
Chris@16
|
34 #include <boost/proto/generate.hpp>
|
Chris@16
|
35 #include <boost/proto/detail/remove_typename.hpp>
|
Chris@16
|
36
|
Chris@101
|
37 #if defined(_MSC_VER)
|
Chris@16
|
38 # pragma warning(push)
|
Chris@16
|
39 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
|
Chris@16
|
40 #endif
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost { namespace proto
|
Chris@16
|
43 {
|
Chris@16
|
44 #ifdef __GNUC__
|
Chris@16
|
45 /// INTERNAL ONLY
|
Chris@16
|
46 ///
|
Chris@16
|
47 # define BOOST_PROTO_ADDROF(x) ((char const volatile*)boost::addressof(x))
|
Chris@16
|
48 /// INTERNAL ONLY
|
Chris@16
|
49 ///
|
Chris@16
|
50 # define BOOST_PROTO_OFFSETOF(s,m) (BOOST_PROTO_ADDROF((((s *)this)->m)) - BOOST_PROTO_ADDROF(*((s *)this)))
|
Chris@16
|
51 #else
|
Chris@16
|
52 /// INTERNAL ONLY
|
Chris@16
|
53 ///
|
Chris@16
|
54 # define BOOST_PROTO_OFFSETOF offsetof
|
Chris@16
|
55 #endif
|
Chris@16
|
56
|
Chris@16
|
57 /// INTERNAL ONLY
|
Chris@16
|
58 ///
|
Chris@16
|
59 #define BOOST_PROTO_CONST() const
|
Chris@16
|
60
|
Chris@16
|
61 /// INTERNAL ONLY
|
Chris@16
|
62 ///
|
Chris@16
|
63 #define BOOST_PROTO_TYPENAME() typename
|
Chris@16
|
64
|
Chris@16
|
65 /// INTERNAL ONLY
|
Chris@16
|
66 ///
|
Chris@16
|
67 #define BOOST_PROTO_TEMPLATE_YES_(Z, N) template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>
|
Chris@16
|
68
|
Chris@16
|
69 /// INTERNAL ONLY
|
Chris@16
|
70 ///
|
Chris@16
|
71 #define BOOST_PROTO_TEMPLATE_NO_(Z, N)
|
Chris@16
|
72
|
Chris@16
|
73 /// INTERNAL ONLY
|
Chris@16
|
74 ///
|
Chris@16
|
75 #define BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, Const) \
|
Chris@16
|
76 BOOST_PP_IF(N, BOOST_PROTO_TEMPLATE_YES_, BOOST_PROTO_TEMPLATE_NO_)(Z, N) \
|
Chris@16
|
77 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
78 typename BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
79 proto_generator( \
|
Chris@16
|
80 typename boost::proto::result_of::BOOST_PP_CAT(funop, N)< \
|
Chris@16
|
81 proto_derived_expr Const() \
|
Chris@16
|
82 , proto_domain \
|
Chris@16
|
83 BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A) \
|
Chris@16
|
84 >::type \
|
Chris@16
|
85 ) \
|
Chris@16
|
86 >::type const \
|
Chris@16
|
87 operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) Const() \
|
Chris@16
|
88 { \
|
Chris@16
|
89 typedef boost::proto::result_of::BOOST_PP_CAT(funop, N)< \
|
Chris@16
|
90 proto_derived_expr Const() \
|
Chris@16
|
91 , proto_domain \
|
Chris@16
|
92 BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A) \
|
Chris@16
|
93 > funop; \
|
Chris@16
|
94 return proto_generator()( \
|
Chris@16
|
95 funop::call( \
|
Chris@16
|
96 *static_cast<proto_derived_expr Const() *>(this) \
|
Chris@16
|
97 BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, a) \
|
Chris@16
|
98 ) \
|
Chris@16
|
99 ); \
|
Chris@16
|
100 } \
|
Chris@16
|
101 /**/
|
Chris@16
|
102
|
Chris@16
|
103 /// INTERNAL ONLY
|
Chris@16
|
104 ///
|
Chris@16
|
105 #define BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(Const) \
|
Chris@16
|
106 template<typename... A> \
|
Chris@16
|
107 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
108 typename BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
109 proto_generator( \
|
Chris@16
|
110 typename boost::proto::result_of::funop< \
|
Chris@16
|
111 proto_derived_expr Const()(A const &...) \
|
Chris@16
|
112 , proto_derived_expr \
|
Chris@16
|
113 , proto_domain \
|
Chris@16
|
114 >::type \
|
Chris@16
|
115 ) \
|
Chris@16
|
116 >::type const \
|
Chris@16
|
117 operator ()(A const &...a) Const() \
|
Chris@16
|
118 { \
|
Chris@16
|
119 typedef boost::proto::result_of::funop< \
|
Chris@16
|
120 proto_derived_expr Const()(A const &...) \
|
Chris@16
|
121 , proto_derived_expr \
|
Chris@16
|
122 , proto_domain \
|
Chris@16
|
123 > funop; \
|
Chris@16
|
124 return proto_generator()( \
|
Chris@16
|
125 funop::call( \
|
Chris@16
|
126 *static_cast<proto_derived_expr Const() *>(this) \
|
Chris@16
|
127 , a... \
|
Chris@16
|
128 ) \
|
Chris@16
|
129 ); \
|
Chris@16
|
130 } \
|
Chris@16
|
131 /**/
|
Chris@16
|
132
|
Chris@16
|
133 /// INTERNAL ONLY
|
Chris@16
|
134 ///
|
Chris@16
|
135 #define BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA) \
|
Chris@16
|
136 BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PROTO_CONST) \
|
Chris@16
|
137 /**/
|
Chris@16
|
138
|
Chris@16
|
139 /// INTERNAL ONLY
|
Chris@16
|
140 ///
|
Chris@16
|
141 #define BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA) \
|
Chris@16
|
142 BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PP_EMPTY) \
|
Chris@16
|
143 /**/
|
Chris@16
|
144
|
Chris@16
|
145 /// INTERNAL ONLY
|
Chris@16
|
146 ///
|
Chris@16
|
147 #define BOOST_PROTO_DEFINE_FUN_OP(Z, N, DATA) \
|
Chris@16
|
148 BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA) \
|
Chris@16
|
149 BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA) \
|
Chris@16
|
150 /**/
|
Chris@16
|
151
|
Chris@16
|
152 /// INTERNAL ONLY
|
Chris@16
|
153 ///
|
Chris@16
|
154 #define BOOST_PROTO_EXTENDS_CHILD(Z, N, DATA) \
|
Chris@16
|
155 typedef \
|
Chris@16
|
156 typename proto_base_expr::BOOST_PP_CAT(proto_child, N) \
|
Chris@16
|
157 BOOST_PP_CAT(proto_child, N); \
|
Chris@16
|
158 /**/
|
Chris@16
|
159
|
Chris@16
|
160 #define BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain) \
|
Chris@16
|
161 Expr proto_expr_; \
|
Chris@16
|
162 \
|
Chris@16
|
163 typedef Expr proto_base_expr_; /**< INTERNAL ONLY */ \
|
Chris@16
|
164 typedef typename proto_base_expr_::proto_base_expr proto_base_expr; \
|
Chris@16
|
165 typedef BOOST_PROTO_REMOVE_TYPENAME(Domain) proto_domain; \
|
Chris@16
|
166 typedef Derived proto_derived_expr; \
|
Chris@16
|
167 typedef Domain::proto_generator proto_generator; \
|
Chris@16
|
168 typedef typename proto_base_expr::proto_tag proto_tag; \
|
Chris@16
|
169 typedef typename proto_base_expr::proto_args proto_args; \
|
Chris@16
|
170 typedef typename proto_base_expr::proto_arity proto_arity; \
|
Chris@16
|
171 typedef typename proto_base_expr::proto_grammar proto_grammar; \
|
Chris@16
|
172 typedef typename proto_base_expr::address_of_hack_type_ proto_address_of_hack_type_; \
|
Chris@16
|
173 typedef void proto_is_expr_; /**< INTERNAL ONLY */ \
|
Chris@16
|
174 static const long proto_arity_c = proto_base_expr::proto_arity_c; \
|
Chris@16
|
175 typedef boost::proto::tag::proto_expr<proto_tag, proto_domain> fusion_tag; \
|
Chris@16
|
176 BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, BOOST_PROTO_EXTENDS_CHILD, ~) \
|
Chris@16
|
177 \
|
Chris@16
|
178 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
179 static proto_derived_expr const make(Expr const &e) \
|
Chris@16
|
180 { \
|
Chris@16
|
181 proto_derived_expr that = {e}; \
|
Chris@16
|
182 return that; \
|
Chris@16
|
183 } \
|
Chris@16
|
184 \
|
Chris@16
|
185 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
186 proto_base_expr &proto_base() \
|
Chris@16
|
187 { \
|
Chris@16
|
188 return this->proto_expr_.proto_base(); \
|
Chris@16
|
189 } \
|
Chris@16
|
190 \
|
Chris@16
|
191 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
192 proto_base_expr const &proto_base() const \
|
Chris@16
|
193 { \
|
Chris@16
|
194 return this->proto_expr_.proto_base(); \
|
Chris@16
|
195 } \
|
Chris@16
|
196 \
|
Chris@16
|
197 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
198 operator proto_address_of_hack_type_() const \
|
Chris@16
|
199 { \
|
Chris@16
|
200 return boost::addressof(this->proto_base().child0); \
|
Chris@16
|
201 } \
|
Chris@16
|
202 /**/
|
Chris@16
|
203
|
Chris@16
|
204 #define BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain) \
|
Chris@16
|
205 BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain) \
|
Chris@16
|
206 typedef void proto_is_aggregate_; \
|
Chris@16
|
207 /**< INTERNAL ONLY */
|
Chris@16
|
208
|
Chris@16
|
209 #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, Const, Typename) \
|
Chris@16
|
210 BOOST_PROTO_DISABLE_MSVC_C4522 \
|
Chris@16
|
211 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
212 Typename() BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
213 Typename() This::proto_generator( \
|
Chris@16
|
214 Typename() boost::proto::base_expr< \
|
Chris@16
|
215 Typename() This::proto_domain \
|
Chris@16
|
216 , boost::proto::tag::assign \
|
Chris@16
|
217 , boost::proto::list2< \
|
Chris@16
|
218 This & \
|
Chris@16
|
219 , This Const() & \
|
Chris@16
|
220 > \
|
Chris@16
|
221 >::type \
|
Chris@16
|
222 ) \
|
Chris@16
|
223 >::type const \
|
Chris@16
|
224 operator =(This Const() &a) \
|
Chris@16
|
225 { \
|
Chris@16
|
226 typedef \
|
Chris@16
|
227 Typename() boost::proto::base_expr< \
|
Chris@16
|
228 Typename() This::proto_domain \
|
Chris@16
|
229 , boost::proto::tag::assign \
|
Chris@16
|
230 , boost::proto::list2< \
|
Chris@16
|
231 This & \
|
Chris@16
|
232 , This Const() & \
|
Chris@16
|
233 > \
|
Chris@16
|
234 >::type \
|
Chris@16
|
235 that_type; \
|
Chris@16
|
236 that_type const that = { \
|
Chris@16
|
237 *this \
|
Chris@16
|
238 , a \
|
Chris@16
|
239 }; \
|
Chris@16
|
240 return Typename() This::proto_generator()(that); \
|
Chris@16
|
241 } \
|
Chris@16
|
242 /**/
|
Chris@16
|
243
|
Chris@16
|
244 // MSVC 8.0 and higher seem to need copy-assignment operator to be overloaded on *both*
|
Chris@16
|
245 // const and non-const rhs arguments.
|
Chris@16
|
246 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) && (BOOST_MSVC > 1310)
|
Chris@16
|
247 #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename) \
|
Chris@16
|
248 BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PP_EMPTY, Typename) \
|
Chris@16
|
249 BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename) \
|
Chris@16
|
250 /**/
|
Chris@16
|
251 #else
|
Chris@16
|
252 #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename) \
|
Chris@16
|
253 BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename) \
|
Chris@16
|
254 /**/
|
Chris@16
|
255 #endif
|
Chris@16
|
256
|
Chris@16
|
257 /// INTERNAL ONLY
|
Chris@16
|
258 ///
|
Chris@16
|
259 #define BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(ThisConst, ThatConst) \
|
Chris@16
|
260 template<typename A> \
|
Chris@16
|
261 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
262 typename BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
263 proto_generator( \
|
Chris@16
|
264 typename boost::proto::base_expr< \
|
Chris@16
|
265 proto_domain \
|
Chris@16
|
266 , boost::proto::tag::assign \
|
Chris@16
|
267 , boost::proto::list2< \
|
Chris@16
|
268 proto_derived_expr ThisConst() & \
|
Chris@16
|
269 , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
|
Chris@16
|
270 > \
|
Chris@16
|
271 >::type \
|
Chris@16
|
272 ) \
|
Chris@16
|
273 >::type const \
|
Chris@16
|
274 operator =(A ThatConst() &a) ThisConst() \
|
Chris@16
|
275 { \
|
Chris@16
|
276 typedef \
|
Chris@16
|
277 typename boost::proto::base_expr< \
|
Chris@16
|
278 proto_domain \
|
Chris@16
|
279 , boost::proto::tag::assign \
|
Chris@16
|
280 , boost::proto::list2< \
|
Chris@16
|
281 proto_derived_expr ThisConst() & \
|
Chris@16
|
282 , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
|
Chris@16
|
283 > \
|
Chris@16
|
284 >::type \
|
Chris@16
|
285 that_type; \
|
Chris@16
|
286 that_type const that = { \
|
Chris@16
|
287 *static_cast<proto_derived_expr ThisConst() *>(this) \
|
Chris@16
|
288 , boost::proto::as_child<proto_domain>(a) \
|
Chris@16
|
289 }; \
|
Chris@16
|
290 return proto_generator()(that); \
|
Chris@16
|
291 } \
|
Chris@16
|
292 /**/
|
Chris@16
|
293
|
Chris@16
|
294 #define BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
|
Chris@16
|
295 BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY) \
|
Chris@16
|
296 BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST) \
|
Chris@16
|
297 /**/
|
Chris@16
|
298
|
Chris@16
|
299 #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
|
Chris@16
|
300 BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY) \
|
Chris@16
|
301 BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST) \
|
Chris@16
|
302 /**/
|
Chris@16
|
303
|
Chris@16
|
304 #define BOOST_PROTO_EXTENDS_ASSIGN_() \
|
Chris@16
|
305 BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
|
Chris@16
|
306 BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
|
Chris@16
|
307 /**/
|
Chris@16
|
308
|
Chris@16
|
309 #define BOOST_PROTO_EXTENDS_ASSIGN_CONST() \
|
Chris@16
|
310 BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
|
Chris@16
|
311 BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
|
Chris@16
|
312 /**/
|
Chris@16
|
313
|
Chris@16
|
314 #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST() \
|
Chris@16
|
315 BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
|
Chris@16
|
316 BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
|
Chris@16
|
317 /**/
|
Chris@16
|
318
|
Chris@16
|
319 #define BOOST_PROTO_EXTENDS_ASSIGN() \
|
Chris@16
|
320 BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
|
Chris@16
|
321 BOOST_PROTO_EXTENDS_ASSIGN_() \
|
Chris@16
|
322 /**/
|
Chris@16
|
323
|
Chris@16
|
324 /// INTERNAL ONLY
|
Chris@16
|
325 ///
|
Chris@16
|
326 #define BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(ThisConst, ThatConst) \
|
Chris@16
|
327 template<typename A> \
|
Chris@16
|
328 BOOST_PROTO_DISABLE_MSVC_C4714 BOOST_FORCEINLINE \
|
Chris@16
|
329 typename BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
330 proto_generator( \
|
Chris@16
|
331 typename boost::proto::base_expr< \
|
Chris@16
|
332 proto_domain \
|
Chris@16
|
333 , boost::proto::tag::subscript \
|
Chris@16
|
334 , boost::proto::list2< \
|
Chris@16
|
335 proto_derived_expr ThisConst() & \
|
Chris@16
|
336 , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
|
Chris@16
|
337 > \
|
Chris@16
|
338 >::type \
|
Chris@16
|
339 ) \
|
Chris@16
|
340 >::type const \
|
Chris@16
|
341 operator [](A ThatConst() &a) ThisConst() \
|
Chris@16
|
342 { \
|
Chris@16
|
343 typedef \
|
Chris@16
|
344 typename boost::proto::base_expr< \
|
Chris@16
|
345 proto_domain \
|
Chris@16
|
346 , boost::proto::tag::subscript \
|
Chris@16
|
347 , boost::proto::list2< \
|
Chris@16
|
348 proto_derived_expr ThisConst() & \
|
Chris@16
|
349 , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
|
Chris@16
|
350 > \
|
Chris@16
|
351 >::type \
|
Chris@16
|
352 that_type; \
|
Chris@16
|
353 that_type const that = { \
|
Chris@16
|
354 *static_cast<proto_derived_expr ThisConst() *>(this) \
|
Chris@16
|
355 , boost::proto::as_child<proto_domain>(a) \
|
Chris@16
|
356 }; \
|
Chris@16
|
357 return proto_generator()(that); \
|
Chris@16
|
358 } \
|
Chris@16
|
359 /**/
|
Chris@16
|
360
|
Chris@16
|
361 #define BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST() \
|
Chris@16
|
362 BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY) \
|
Chris@16
|
363 BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST) \
|
Chris@16
|
364 /**/
|
Chris@16
|
365
|
Chris@16
|
366 #define BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST() \
|
Chris@16
|
367 BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY) \
|
Chris@16
|
368 BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST) \
|
Chris@16
|
369 /**/
|
Chris@16
|
370
|
Chris@16
|
371 #define BOOST_PROTO_EXTENDS_SUBSCRIPT() \
|
Chris@16
|
372 BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST() \
|
Chris@16
|
373 BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST() \
|
Chris@16
|
374 /**/
|
Chris@16
|
375
|
Chris@16
|
376 /// INTERNAL ONLY
|
Chris@16
|
377 ///
|
Chris@16
|
378 #define BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
379 template<typename Sig> \
|
Chris@16
|
380 struct result \
|
Chris@16
|
381 { \
|
Chris@16
|
382 typedef \
|
Chris@16
|
383 typename BOOST_PROTO_RESULT_OF< \
|
Chris@16
|
384 proto_generator( \
|
Chris@16
|
385 typename boost::proto::result_of::funop< \
|
Chris@16
|
386 Sig \
|
Chris@16
|
387 , proto_derived_expr \
|
Chris@16
|
388 , proto_domain \
|
Chris@16
|
389 >::type \
|
Chris@16
|
390 ) \
|
Chris@16
|
391 >::type const \
|
Chris@16
|
392 type; \
|
Chris@16
|
393 }; \
|
Chris@16
|
394 /**/
|
Chris@16
|
395
|
Chris@16
|
396 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
Chris@16
|
397 #define BOOST_PROTO_EXTENDS_FUNCTION_CONST() \
|
Chris@16
|
398 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
399 BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST) \
|
Chris@16
|
400 /**/
|
Chris@16
|
401
|
Chris@16
|
402 #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST() \
|
Chris@16
|
403 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
404 BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY) \
|
Chris@16
|
405 /**/
|
Chris@16
|
406
|
Chris@16
|
407 #define BOOST_PROTO_EXTENDS_FUNCTION() \
|
Chris@16
|
408 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
409 BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY) \
|
Chris@16
|
410 BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST) \
|
Chris@16
|
411 /**/
|
Chris@16
|
412 #else
|
Chris@16
|
413 #define BOOST_PROTO_EXTENDS_FUNCTION_CONST() \
|
Chris@16
|
414 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
415 BOOST_PP_REPEAT_FROM_TO( \
|
Chris@16
|
416 0 \
|
Chris@16
|
417 , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
|
Chris@16
|
418 , BOOST_PROTO_DEFINE_FUN_OP_CONST \
|
Chris@16
|
419 , ~ \
|
Chris@16
|
420 ) \
|
Chris@16
|
421 /**/
|
Chris@16
|
422
|
Chris@16
|
423 #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST() \
|
Chris@16
|
424 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
425 BOOST_PP_REPEAT_FROM_TO( \
|
Chris@16
|
426 0 \
|
Chris@16
|
427 , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
|
Chris@16
|
428 , BOOST_PROTO_DEFINE_FUN_OP_NON_CONST \
|
Chris@16
|
429 , ~ \
|
Chris@16
|
430 ) \
|
Chris@16
|
431 /**/
|
Chris@16
|
432
|
Chris@16
|
433 #define BOOST_PROTO_EXTENDS_FUNCTION() \
|
Chris@16
|
434 BOOST_PROTO_EXTENDS_FUNCTION_() \
|
Chris@16
|
435 BOOST_PP_REPEAT_FROM_TO( \
|
Chris@16
|
436 0 \
|
Chris@16
|
437 , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
|
Chris@16
|
438 , BOOST_PROTO_DEFINE_FUN_OP \
|
Chris@16
|
439 , ~ \
|
Chris@16
|
440 ) \
|
Chris@16
|
441 /**/
|
Chris@16
|
442 #endif
|
Chris@16
|
443
|
Chris@16
|
444 #define BOOST_PROTO_EXTENDS(Expr, Derived, Domain) \
|
Chris@16
|
445 BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain) \
|
Chris@16
|
446 BOOST_PROTO_EXTENDS_ASSIGN() \
|
Chris@16
|
447 BOOST_PROTO_EXTENDS_SUBSCRIPT() \
|
Chris@16
|
448 BOOST_PROTO_EXTENDS_FUNCTION() \
|
Chris@16
|
449 /**/
|
Chris@16
|
450
|
Chris@16
|
451 #define BOOST_PROTO_EXTENDS_USING_ASSIGN(Derived) \
|
Chris@16
|
452 typedef typename Derived::proto_extends proto_extends; \
|
Chris@16
|
453 using proto_extends::operator =; \
|
Chris@16
|
454 BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PROTO_TYPENAME) \
|
Chris@16
|
455 /**/
|
Chris@16
|
456
|
Chris@16
|
457 #define BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT(Derived) \
|
Chris@16
|
458 typedef Derived::proto_extends proto_extends; \
|
Chris@16
|
459 using proto_extends::operator =; \
|
Chris@16
|
460 BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PP_EMPTY) \
|
Chris@16
|
461 /**/
|
Chris@16
|
462
|
Chris@16
|
463 namespace exprns_
|
Chris@16
|
464 {
|
Chris@16
|
465 /// \brief Empty type to be used as a dummy template parameter of
|
Chris@16
|
466 /// POD expression wrappers. It allows argument-dependent lookup
|
Chris@16
|
467 /// to find Proto's operator overloads.
|
Chris@16
|
468 ///
|
Chris@16
|
469 /// \c proto::is_proto_expr allows argument-dependent lookup
|
Chris@16
|
470 /// to find Proto's operator overloads. For example:
|
Chris@16
|
471 ///
|
Chris@16
|
472 /// \code
|
Chris@16
|
473 /// template<typename T, typename Dummy = proto::is_proto_expr>
|
Chris@16
|
474 /// struct my_terminal
|
Chris@16
|
475 /// {
|
Chris@16
|
476 /// BOOST_PROTO_BASIC_EXTENDS(
|
Chris@16
|
477 /// typename proto::terminal<T>::type
|
Chris@16
|
478 /// , my_terminal<T>
|
Chris@16
|
479 /// , default_domain
|
Chris@16
|
480 /// )
|
Chris@16
|
481 /// };
|
Chris@16
|
482 ///
|
Chris@16
|
483 /// // ...
|
Chris@16
|
484 /// my_terminal<int> _1, _2;
|
Chris@16
|
485 /// _1 + _2; // OK, uses proto::operator+
|
Chris@16
|
486 /// \endcode
|
Chris@16
|
487 ///
|
Chris@16
|
488 /// Without the second \c Dummy template parameter, Proto's operator
|
Chris@16
|
489 /// overloads would not be considered by name lookup.
|
Chris@16
|
490 struct is_proto_expr
|
Chris@16
|
491 {};
|
Chris@16
|
492
|
Chris@16
|
493 /// \brief extends\<\> class template for adding behaviors to a Proto expression template
|
Chris@16
|
494 ///
|
Chris@16
|
495 template<
|
Chris@16
|
496 typename Expr
|
Chris@16
|
497 , typename Derived
|
Chris@16
|
498 , typename Domain // = proto::default_domain
|
Chris@16
|
499 , long Arity // = Expr::proto_arity_c
|
Chris@16
|
500 >
|
Chris@16
|
501 struct extends
|
Chris@16
|
502 {
|
Chris@16
|
503 BOOST_FORCEINLINE
|
Chris@16
|
504 extends()
|
Chris@16
|
505 : proto_expr_()
|
Chris@16
|
506 {}
|
Chris@16
|
507
|
Chris@16
|
508 BOOST_FORCEINLINE
|
Chris@16
|
509 extends(extends const &that)
|
Chris@16
|
510 : proto_expr_(that.proto_expr_)
|
Chris@16
|
511 {}
|
Chris@16
|
512
|
Chris@16
|
513 BOOST_FORCEINLINE
|
Chris@16
|
514 extends(Expr const &expr_)
|
Chris@16
|
515 : proto_expr_(expr_)
|
Chris@16
|
516 {}
|
Chris@16
|
517
|
Chris@16
|
518 typedef extends proto_extends;
|
Chris@16
|
519 BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, typename Domain)
|
Chris@16
|
520 BOOST_PROTO_EXTENDS_ASSIGN_CONST_()
|
Chris@16
|
521 BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST()
|
Chris@16
|
522
|
Chris@16
|
523 // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
|
Chris@16
|
524 // nested preprocessor loops, use file iteration here to generate
|
Chris@16
|
525 // the operator() overloads, which is more efficient.
|
Chris@16
|
526 #include <boost/proto/detail/extends_funop_const.hpp>
|
Chris@16
|
527 };
|
Chris@16
|
528
|
Chris@16
|
529 /// \brief extends\<\> class template for adding behaviors to a Proto expression template
|
Chris@16
|
530 ///
|
Chris@16
|
531 template<typename Expr, typename Derived, typename Domain>
|
Chris@16
|
532 struct extends<Expr, Derived, Domain, 0>
|
Chris@16
|
533 {
|
Chris@16
|
534 BOOST_FORCEINLINE
|
Chris@16
|
535 extends()
|
Chris@16
|
536 : proto_expr_()
|
Chris@16
|
537 {}
|
Chris@16
|
538
|
Chris@16
|
539 BOOST_FORCEINLINE
|
Chris@16
|
540 extends(extends const &that)
|
Chris@16
|
541 : proto_expr_(that.proto_expr_)
|
Chris@16
|
542 {}
|
Chris@16
|
543
|
Chris@16
|
544 BOOST_FORCEINLINE
|
Chris@16
|
545 extends(Expr const &expr_)
|
Chris@16
|
546 : proto_expr_(expr_)
|
Chris@16
|
547 {}
|
Chris@16
|
548
|
Chris@16
|
549 typedef extends proto_extends;
|
Chris@16
|
550 BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, typename Domain)
|
Chris@16
|
551 BOOST_PROTO_EXTENDS_ASSIGN_()
|
Chris@16
|
552 BOOST_PROTO_EXTENDS_SUBSCRIPT()
|
Chris@16
|
553
|
Chris@16
|
554 // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
|
Chris@16
|
555 // nested preprocessor loops, use file iteration here to generate
|
Chris@16
|
556 // the operator() overloads, which is more efficient.
|
Chris@16
|
557 #include <boost/proto/detail/extends_funop.hpp>
|
Chris@16
|
558 };
|
Chris@16
|
559
|
Chris@16
|
560 /// INTERNAL ONLY
|
Chris@16
|
561 ///
|
Chris@16
|
562 template<typename This, typename Fun, typename Domain>
|
Chris@16
|
563 struct virtual_member
|
Chris@16
|
564 {
|
Chris@16
|
565 typedef Domain proto_domain;
|
Chris@16
|
566 typedef typename Domain::proto_generator proto_generator;
|
Chris@16
|
567 typedef virtual_member<This, Fun, Domain> proto_derived_expr;
|
Chris@16
|
568 typedef tag::member proto_tag;
|
Chris@16
|
569 typedef list2<This &, expr<tag::terminal, term<Fun> > const &> proto_args;
|
Chris@16
|
570 typedef mpl::long_<2> proto_arity;
|
Chris@16
|
571 typedef detail::not_a_valid_type proto_address_of_hack_type_;
|
Chris@16
|
572 typedef void proto_is_expr_; /**< INTERNAL ONLY */
|
Chris@16
|
573 static const long proto_arity_c = 2;
|
Chris@16
|
574 typedef boost::proto::tag::proto_expr<proto_tag, Domain> fusion_tag;
|
Chris@16
|
575 typedef This &proto_child0;
|
Chris@16
|
576 typedef expr<tag::terminal, term<Fun> > const &proto_child1;
|
Chris@16
|
577 typedef expr<proto_tag, proto_args, proto_arity_c> proto_base_expr;
|
Chris@16
|
578 typedef basic_expr<proto_tag, proto_args, proto_arity_c> proto_grammar;
|
Chris@16
|
579 typedef void proto_is_aggregate_; /**< INTERNAL ONLY */
|
Chris@16
|
580
|
Chris@16
|
581 BOOST_PROTO_EXTENDS_ASSIGN_()
|
Chris@16
|
582 BOOST_PROTO_EXTENDS_SUBSCRIPT()
|
Chris@16
|
583
|
Chris@16
|
584 // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
|
Chris@16
|
585 // nested preprocessor loops, use file iteration here to generate
|
Chris@16
|
586 // the operator() overloads, which is more efficient.
|
Chris@16
|
587 #define BOOST_PROTO_NO_WAVE_OUTPUT
|
Chris@16
|
588 #include <boost/proto/detail/extends_funop.hpp>
|
Chris@16
|
589 #undef BOOST_PROTO_NO_WAVE_OUTPUT
|
Chris@16
|
590
|
Chris@16
|
591 BOOST_FORCEINLINE
|
Chris@16
|
592 proto_base_expr const proto_base() const
|
Chris@16
|
593 {
|
Chris@16
|
594 proto_base_expr that = {this->child0(), this->child1()};
|
Chris@16
|
595 return that;
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 BOOST_FORCEINLINE
|
Chris@16
|
599 proto_child0 child0() const
|
Chris@16
|
600 {
|
Chris@16
|
601 using std::size_t;
|
Chris@16
|
602 return *(This *)((char *)this - BOOST_PROTO_OFFSETOF(This, proto_member_union_start_));
|
Chris@16
|
603 }
|
Chris@16
|
604
|
Chris@16
|
605 BOOST_FORCEINLINE
|
Chris@16
|
606 proto_child1 child1() const
|
Chris@16
|
607 {
|
Chris@16
|
608 static expr<tag::terminal, term<Fun>, 0> const that = {Fun()};
|
Chris@16
|
609 return that;
|
Chris@16
|
610 }
|
Chris@16
|
611 };
|
Chris@16
|
612
|
Chris@16
|
613 /// INTERNAL ONLY
|
Chris@16
|
614 ///
|
Chris@16
|
615 #define BOOST_PROTO_EXTENDS_MEMBER_(R, DOMAIN, ELEM) \
|
Chris@16
|
616 boost::proto::exprns_::virtual_member< \
|
Chris@16
|
617 proto_derived_expr \
|
Chris@16
|
618 , BOOST_PP_TUPLE_ELEM(2, 0, ELEM) \
|
Chris@16
|
619 , DOMAIN \
|
Chris@16
|
620 > BOOST_PP_TUPLE_ELEM(2, 1, ELEM); \
|
Chris@16
|
621 /**/
|
Chris@16
|
622
|
Chris@16
|
623 /// \brief For declaring virtual data members in an extension class.
|
Chris@16
|
624 ///
|
Chris@16
|
625 #define BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, DOMAIN) \
|
Chris@16
|
626 union \
|
Chris@16
|
627 { \
|
Chris@16
|
628 char proto_member_union_start_; \
|
Chris@16
|
629 BOOST_PP_SEQ_FOR_EACH(BOOST_PROTO_EXTENDS_MEMBER_, DOMAIN, SEQ) \
|
Chris@16
|
630 }; \
|
Chris@16
|
631 /**/
|
Chris@16
|
632
|
Chris@16
|
633 /// \brief For declaring virtual data members in an extension class.
|
Chris@16
|
634 ///
|
Chris@16
|
635 #define BOOST_PROTO_EXTENDS_MEMBERS(SEQ) \
|
Chris@16
|
636 BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, proto_domain) \
|
Chris@16
|
637 /**/
|
Chris@16
|
638
|
Chris@16
|
639 }
|
Chris@16
|
640
|
Chris@16
|
641 }}
|
Chris@16
|
642
|
Chris@101
|
643 #if defined(_MSC_VER)
|
Chris@16
|
644 # pragma warning(pop)
|
Chris@16
|
645 #endif
|
Chris@16
|
646
|
Chris@16
|
647 #endif
|