]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | /// \file generate.hpp | |
3 | /// Contains definition of generate\<\> class template, which end users can | |
4 | /// specialize for generating domain-specific expression wrappers. | |
5 | // | |
6 | // Copyright 2008 Eric Niebler. Distributed under the Boost | |
7 | // Software License, Version 1.0. (See accompanying file | |
8 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | ||
10 | #ifndef BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 | |
11 | #define BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 | |
12 | ||
13 | #include <boost/config.hpp> | |
14 | #include <boost/version.hpp> | |
15 | #include <boost/preprocessor/cat.hpp> | |
16 | #include <boost/preprocessor/iteration/iterate.hpp> | |
17 | #include <boost/preprocessor/facilities/intercept.hpp> | |
18 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
19 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
20 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
21 | #include <boost/mpl/bool.hpp> | |
22 | #include <boost/utility/enable_if.hpp> | |
23 | #include <boost/utility/result_of.hpp> | |
24 | #include <boost/proto/proto_fwd.hpp> | |
25 | #include <boost/proto/args.hpp> | |
26 | ||
27 | #if defined(_MSC_VER) | |
28 | # pragma warning(push) | |
29 | # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined | |
30 | #endif | |
31 | ||
32 | namespace boost { namespace proto | |
33 | { | |
34 | ||
35 | namespace detail | |
36 | { | |
37 | template<typename Expr> | |
38 | struct by_value_generator_; | |
39 | ||
40 | template<typename Tag, typename Arg> | |
41 | struct by_value_generator_<proto::expr<Tag, term<Arg>, 0> > | |
42 | { | |
43 | typedef | |
44 | proto::expr< | |
45 | Tag | |
46 | , term<typename detail::term_traits<Arg>::value_type> | |
47 | , 0 | |
48 | > | |
49 | type; | |
50 | ||
51 | BOOST_FORCEINLINE | |
52 | static type const call(proto::expr<Tag, term<Arg>, 0> const &e) | |
53 | { | |
54 | type that = {e.child0}; | |
55 | return that; | |
56 | } | |
57 | }; | |
58 | ||
59 | template<typename Tag, typename Arg> | |
60 | struct by_value_generator_<proto::basic_expr<Tag, term<Arg>, 0> > | |
61 | { | |
62 | typedef | |
63 | proto::basic_expr< | |
64 | Tag | |
65 | , term<typename detail::term_traits<Arg>::value_type> | |
66 | , 0 | |
67 | > | |
68 | type; | |
69 | ||
70 | BOOST_FORCEINLINE | |
71 | static type const call(proto::basic_expr<Tag, term<Arg>, 0> const &e) | |
72 | { | |
73 | type that = {e.child0}; | |
74 | return that; | |
75 | } | |
76 | }; | |
77 | ||
78 | // Include the other specializations of by_value_generator_ | |
79 | #include <boost/proto/detail/generate_by_value.hpp> | |
80 | } | |
81 | ||
82 | /// \brief Annotate a generator to indicate that it would | |
83 | /// prefer to be passed instances of \c proto::basic_expr\<\> rather | |
84 | /// than \c proto::expr\<\>. <tt>use_basic_expr\<Generator\></tt> is | |
85 | /// itself a generator. | |
86 | /// | |
87 | template<typename Generator> | |
88 | struct use_basic_expr | |
89 | : Generator | |
90 | { | |
91 | BOOST_PROTO_USE_BASIC_EXPR() | |
92 | }; | |
93 | ||
94 | /// \brief A simple generator that passes an expression | |
95 | /// through unchanged. | |
96 | /// | |
97 | /// Generators are intended for use as the first template parameter | |
98 | /// to the \c domain\<\> class template and control if and how | |
99 | /// expressions within that domain are to be customized. | |
100 | /// The \c default_generator makes no modifications to the expressions | |
101 | /// passed to it. | |
102 | struct default_generator | |
103 | { | |
104 | BOOST_PROTO_CALLABLE() | |
105 | ||
106 | template<typename Sig> | |
107 | struct result; | |
108 | ||
109 | template<typename This, typename Expr> | |
110 | struct result<This(Expr)> | |
111 | { | |
112 | typedef Expr type; | |
113 | }; | |
114 | ||
115 | /// \param expr A Proto expression | |
116 | /// \return expr | |
117 | template<typename Expr> | |
118 | BOOST_FORCEINLINE | |
119 | BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(Expr, Expr const &) | |
120 | operator ()(Expr const &e) const | |
121 | { | |
122 | return e; | |
123 | } | |
124 | }; | |
125 | ||
126 | /// \brief A simple generator that passes an expression | |
127 | /// through unchanged and specifies a preference for | |
128 | /// \c proto::basic_expr\<\> over \c proto::expr\<\>. | |
129 | /// | |
130 | /// Generators are intended for use as the first template parameter | |
131 | /// to the \c domain\<\> class template and control if and how | |
132 | /// expressions within that domain are to be customized. | |
133 | /// The \c default_generator makes no modifications to the expressions | |
134 | /// passed to it. | |
135 | struct basic_default_generator | |
136 | : proto::use_basic_expr<default_generator> | |
137 | {}; | |
138 | ||
139 | /// \brief A generator that wraps expressions passed | |
140 | /// to it in the specified extension wrapper. | |
141 | /// | |
142 | /// Generators are intended for use as the first template parameter | |
143 | /// to the \c domain\<\> class template and control if and how | |
144 | /// expressions within that domain are to be customized. | |
145 | /// \c generator\<\> wraps each expression passed to it in | |
146 | /// the \c Extends\<\> wrapper. | |
147 | template<template<typename> class Extends> | |
148 | struct generator | |
149 | { | |
150 | BOOST_PROTO_CALLABLE() | |
151 | BOOST_PROTO_USE_BASIC_EXPR() | |
152 | ||
153 | template<typename Sig> | |
154 | struct result; | |
155 | ||
156 | template<typename This, typename Expr> | |
157 | struct result<This(Expr)> | |
158 | { | |
159 | typedef Extends<Expr> type; | |
160 | }; | |
161 | ||
162 | template<typename This, typename Expr> | |
163 | struct result<This(Expr &)> | |
164 | { | |
165 | typedef Extends<Expr> type; | |
166 | }; | |
167 | ||
168 | template<typename This, typename Expr> | |
169 | struct result<This(Expr const &)> | |
170 | { | |
171 | typedef Extends<Expr> type; | |
172 | }; | |
173 | ||
174 | /// \param expr A Proto expression | |
175 | /// \return Extends<Expr>(expr) | |
176 | template<typename Expr> | |
177 | BOOST_FORCEINLINE | |
178 | Extends<Expr> operator ()(Expr const &e) const | |
179 | { | |
180 | return Extends<Expr>(e); | |
181 | } | |
182 | }; | |
183 | ||
184 | /// \brief A generator that wraps expressions passed | |
185 | /// to it in the specified extension wrapper and uses | |
186 | /// aggregate initialization for the wrapper. | |
187 | /// | |
188 | /// Generators are intended for use as the first template parameter | |
189 | /// to the \c domain\<\> class template and control if and how | |
190 | /// expressions within that domain are to be customized. | |
191 | /// \c pod_generator\<\> wraps each expression passed to it in | |
192 | /// the \c Extends\<\> wrapper, and uses aggregate initialzation | |
193 | /// for the wrapped object. | |
194 | template<template<typename> class Extends> | |
195 | struct pod_generator | |
196 | { | |
197 | BOOST_PROTO_CALLABLE() | |
198 | BOOST_PROTO_USE_BASIC_EXPR() | |
199 | ||
200 | template<typename Sig> | |
201 | struct result; | |
202 | ||
203 | template<typename This, typename Expr> | |
204 | struct result<This(Expr)> | |
205 | { | |
206 | typedef Extends<Expr> type; | |
207 | }; | |
208 | ||
209 | template<typename This, typename Expr> | |
210 | struct result<This(Expr &)> | |
211 | { | |
212 | typedef Extends<Expr> type; | |
213 | }; | |
214 | ||
215 | template<typename This, typename Expr> | |
216 | struct result<This(Expr const &)> | |
217 | { | |
218 | typedef Extends<Expr> type; | |
219 | }; | |
220 | ||
221 | /// \param expr The expression to wrap | |
222 | /// \return <tt>Extends\<Expr\> that = {expr}; return that;</tt> | |
223 | template<typename Expr> | |
224 | BOOST_FORCEINLINE | |
225 | Extends<Expr> operator ()(Expr const &e) const | |
226 | { | |
227 | Extends<Expr> that = {e}; | |
228 | return that; | |
229 | } | |
230 | ||
231 | // Work-around for: | |
232 | // https://connect.microsoft.com/VisualStudio/feedback/details/765449/codegen-stack-corruption-using-runtime-checks-when-aggregate-initializing-struct | |
233 | #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) | |
234 | template<typename Class, typename Member> | |
235 | BOOST_FORCEINLINE | |
236 | Extends<expr<tag::terminal, proto::term<Member Class::*> > > operator ()(expr<tag::terminal, proto::term<Member Class::*> > const &e) const | |
237 | { | |
238 | Extends<expr<tag::terminal, proto::term<Member Class::*> > > that; | |
239 | proto::value(that.proto_expr_) = proto::value(e); | |
240 | return that; | |
241 | } | |
242 | ||
243 | template<typename Class, typename Member> | |
244 | BOOST_FORCEINLINE | |
245 | Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > operator ()(basic_expr<tag::terminal, proto::term<Member Class::*> > const &e) const | |
246 | { | |
247 | Extends<basic_expr<tag::terminal, proto::term<Member Class::*> > > that; | |
248 | proto::value(that.proto_expr_) = proto::value(e); | |
249 | return that; | |
250 | } | |
251 | #endif | |
252 | }; | |
253 | ||
254 | /// \brief A generator that replaces child nodes held by | |
255 | /// reference with ones held by value. Use with | |
256 | /// \c compose_generators to forward that result to another | |
257 | /// generator. | |
258 | /// | |
259 | /// Generators are intended for use as the first template parameter | |
260 | /// to the \c domain\<\> class template and control if and how | |
261 | /// expressions within that domain are to be customized. | |
262 | /// \c by_value_generator ensures all child nodes are | |
263 | /// held by value. This generator is typically composed with a | |
264 | /// second generator for further processing, as | |
265 | /// <tt>compose_generators\<by_value_generator, MyGenerator\></tt>. | |
266 | struct by_value_generator | |
267 | { | |
268 | BOOST_PROTO_CALLABLE() | |
269 | ||
270 | template<typename Sig> | |
271 | struct result; | |
272 | ||
273 | template<typename This, typename Expr> | |
274 | struct result<This(Expr)> | |
275 | { | |
276 | typedef | |
277 | typename detail::by_value_generator_<Expr>::type | |
278 | type; | |
279 | }; | |
280 | ||
281 | template<typename This, typename Expr> | |
282 | struct result<This(Expr &)> | |
283 | { | |
284 | typedef | |
285 | typename detail::by_value_generator_<Expr>::type | |
286 | type; | |
287 | }; | |
288 | ||
289 | template<typename This, typename Expr> | |
290 | struct result<This(Expr const &)> | |
291 | { | |
292 | typedef | |
293 | typename detail::by_value_generator_<Expr>::type | |
294 | type; | |
295 | }; | |
296 | ||
297 | /// \param expr The expression to modify. | |
298 | /// \return <tt>deep_copy(expr)</tt> | |
299 | template<typename Expr> | |
300 | BOOST_FORCEINLINE | |
301 | typename result<by_value_generator(Expr)>::type operator ()(Expr const &e) const | |
302 | { | |
303 | return detail::by_value_generator_<Expr>::call(e); | |
304 | } | |
305 | }; | |
306 | ||
307 | /// \brief A composite generator that first applies one | |
308 | /// transform to an expression and then forwards the result | |
309 | /// on to another generator for further transformation. | |
310 | /// | |
311 | /// Generators are intended for use as the first template parameter | |
312 | /// to the \c domain\<\> class template and control if and how | |
313 | /// expressions within that domain are to be customized. | |
314 | /// \c compose_generators\<\> is a composite generator that first | |
315 | /// applies one transform to an expression and then forwards the | |
316 | /// result on to another generator for further transformation. | |
317 | template<typename First, typename Second> | |
318 | struct compose_generators | |
319 | { | |
320 | BOOST_PROTO_CALLABLE() | |
321 | ||
322 | template<typename Sig> | |
323 | struct result; | |
324 | ||
325 | template<typename This, typename Expr> | |
326 | struct result<This(Expr)> | |
327 | { | |
328 | typedef | |
329 | typename Second::template result< | |
330 | Second(typename First::template result<First(Expr)>::type) | |
331 | >::type | |
332 | type; | |
333 | }; | |
334 | ||
335 | template<typename This, typename Expr> | |
336 | struct result<This(Expr &)> | |
337 | { | |
338 | typedef | |
339 | typename Second::template result< | |
340 | Second(typename First::template result<First(Expr)>::type) | |
341 | >::type | |
342 | type; | |
343 | }; | |
344 | ||
345 | template<typename This, typename Expr> | |
346 | struct result<This(Expr const &)> | |
347 | { | |
348 | typedef | |
349 | typename Second::template result< | |
350 | Second(typename First::template result<First(Expr)>::type) | |
351 | >::type | |
352 | type; | |
353 | }; | |
354 | ||
355 | /// \param expr The expression to modify. | |
356 | /// \return Second()(First()(expr)) | |
357 | template<typename Expr> | |
358 | BOOST_FORCEINLINE | |
359 | typename result<compose_generators(Expr)>::type operator ()(Expr const &e) const | |
360 | { | |
361 | return Second()(First()(e)); | |
362 | } | |
363 | }; | |
364 | ||
365 | /// \brief Tests a generator to see whether it would prefer | |
366 | /// to be passed instances of \c proto::basic_expr\<\> rather than | |
367 | /// \c proto::expr\<\>. | |
368 | /// | |
369 | template<typename Generator, typename Void> | |
370 | struct wants_basic_expr | |
371 | : mpl::false_ | |
372 | {}; | |
373 | ||
374 | template<typename Generator> | |
375 | struct wants_basic_expr<Generator, typename Generator::proto_use_basic_expr_> | |
376 | : mpl::true_ | |
377 | {}; | |
378 | ||
379 | /// INTERNAL ONLY | |
380 | template<> | |
381 | struct is_callable<default_generator> | |
382 | : mpl::true_ | |
383 | {}; | |
384 | ||
385 | /// INTERNAL ONLY | |
386 | template<template<typename> class Extends> | |
387 | struct is_callable<generator<Extends> > | |
388 | : mpl::true_ | |
389 | {}; | |
390 | ||
391 | /// INTERNAL ONLY | |
392 | template<template<typename> class Extends> | |
393 | struct is_callable<pod_generator<Extends> > | |
394 | : mpl::true_ | |
395 | {}; | |
396 | ||
397 | /// INTERNAL ONLY | |
398 | template<> | |
399 | struct is_callable<by_value_generator> | |
400 | : mpl::true_ | |
401 | {}; | |
402 | ||
403 | /// INTERNAL ONLY | |
404 | template<typename First, typename Second> | |
405 | struct is_callable<compose_generators<First, Second> > | |
406 | : mpl::true_ | |
407 | {}; | |
408 | ||
409 | }} | |
410 | ||
411 | // Specializations of boost::result_of and boost::tr1_result_of to eliminate | |
412 | // some unnecessary template instantiations | |
413 | namespace boost | |
414 | { | |
415 | template<typename Expr> | |
416 | struct result_of<proto::default_domain(Expr)> | |
417 | { | |
418 | typedef Expr type; | |
419 | }; | |
420 | ||
421 | template<typename Expr> | |
422 | struct result_of<proto::basic_default_domain(Expr)> | |
423 | { | |
424 | typedef Expr type; | |
425 | }; | |
426 | ||
427 | template<typename Expr> | |
428 | struct result_of<proto::default_generator(Expr)> | |
429 | { | |
430 | typedef Expr type; | |
431 | }; | |
432 | ||
433 | template<typename Expr> | |
434 | struct result_of<proto::basic_default_generator(Expr)> | |
435 | { | |
436 | typedef Expr type; | |
437 | }; | |
438 | ||
439 | #if BOOST_VERSION >= 104400 | |
440 | template<typename Expr> | |
441 | struct tr1_result_of<proto::default_domain(Expr)> | |
442 | { | |
443 | typedef Expr type; | |
444 | }; | |
445 | ||
446 | template<typename Expr> | |
447 | struct tr1_result_of<proto::basic_default_domain(Expr)> | |
448 | { | |
449 | typedef Expr type; | |
450 | }; | |
451 | ||
452 | template<typename Expr> | |
453 | struct tr1_result_of<proto::default_generator(Expr)> | |
454 | { | |
455 | typedef Expr type; | |
456 | }; | |
457 | ||
458 | template<typename Expr> | |
459 | struct tr1_result_of<proto::basic_default_generator(Expr)> | |
460 | { | |
461 | typedef Expr type; | |
462 | }; | |
463 | #endif | |
464 | } | |
465 | ||
466 | #if defined(_MSC_VER) | |
467 | # pragma warning(pop) | |
468 | #endif | |
469 | ||
470 | #endif // BOOST_PROTO_GENERATE_HPP_EAN_02_13_2007 |