1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file traits.hpp |
3 | /// Contains definitions for child\<\>, child_c\<\>, left\<\>, |
4 | /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(), |
5 | /// value(), left() and right(). |
6 | // |
7 | // Copyright 2008 Eric Niebler. Distributed under the Boost |
8 | // Software License, Version 1.0. (See accompanying file |
9 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
10 | |
11 | #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 |
12 | #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 |
13 | |
14 | #include <boost/config.hpp> |
15 | #include <boost/detail/workaround.hpp> |
16 | #include <boost/preprocessor/iteration/iterate.hpp> |
17 | #include <boost/preprocessor/repetition/enum.hpp> |
18 | #include <boost/preprocessor/repetition/enum_params.hpp> |
19 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
20 | #include <boost/preprocessor/repetition/repeat.hpp> |
21 | #include <boost/preprocessor/repetition/repeat_from_to.hpp> |
22 | #include <boost/preprocessor/facilities/intercept.hpp> |
23 | #include <boost/preprocessor/arithmetic/sub.hpp> |
24 | #include <boost/static_assert.hpp> |
25 | #include <boost/mpl/bool.hpp> |
26 | #include <boost/proto/detail/template_arity.hpp> |
27 | #include <boost/type_traits/is_pod.hpp> |
28 | #include <boost/type_traits/is_same.hpp> |
29 | #include <boost/type_traits/add_const.hpp> |
30 | #include <boost/proto/proto_fwd.hpp> |
31 | #include <boost/proto/args.hpp> |
32 | #include <boost/proto/domain.hpp> |
33 | #include <boost/proto/transform/pass_through.hpp> |
34 | |
35 | #if defined(_MSC_VER) |
36 | # pragma warning(push) |
37 | # if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) |
38 | # pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored |
39 | # endif |
40 | # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined |
41 | #endif |
42 | |
43 | namespace boost { namespace proto |
44 | { |
45 | namespace detail |
46 | { |
47 | template<typename T, typename Void = void> |
48 | struct if_vararg |
49 | {}; |
50 | |
51 | template<typename T> |
52 | struct if_vararg<T, typename T::proto_is_vararg_> |
53 | : T |
54 | {}; |
55 | |
56 | template<typename T, typename Void = void> |
57 | struct is_callable2_ |
58 | : mpl::false_ |
59 | {}; |
60 | |
61 | template<typename T> |
62 | struct is_callable2_<T, typename T::proto_is_callable_> |
63 | : mpl::true_ |
64 | {}; |
65 | |
66 | template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)> |
67 | struct is_callable_ |
68 | : is_callable2_<T> |
69 | {}; |
70 | |
71 | } |
72 | |
73 | /// \brief Boolean metafunction which detects whether a type is |
74 | /// a callable function object type or not. |
75 | /// |
76 | /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform |
77 | /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a |
78 | /// callable transform or an object transform. (The former are evaluated |
79 | /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If |
80 | /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is |
81 | /// a callable transform; otherwise, it is an object transform. |
82 | /// |
83 | /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt> |
84 | /// is computed as follows: |
85 | /// |
86 | /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx |
87 | /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt> |
88 | /// is <tt>is_same\<YN, proto::callable\>::value</tt>. |
89 | /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef |
90 | /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is |
91 | /// the case for any type that derives from \c proto::callable.) |
92 | /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false. |
93 | template<typename T> |
94 | struct is_callable |
95 | : proto::detail::is_callable_<T> |
96 | {}; |
97 | |
98 | /// INTERNAL ONLY |
99 | /// |
100 | template<> |
101 | struct is_callable<proto::_> |
102 | : mpl::true_ |
103 | {}; |
104 | |
105 | /// INTERNAL ONLY |
106 | /// |
107 | template<> |
108 | struct is_callable<proto::callable> |
109 | : mpl::false_ |
110 | {}; |
111 | |
112 | /// INTERNAL ONLY |
113 | /// |
114 | template<typename PrimitiveTransform, typename X> |
115 | struct is_callable<proto::transform<PrimitiveTransform, X> > |
116 | : mpl::false_ |
117 | {}; |
118 | |
119 | #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0) |
120 | // work around GCC bug |
121 | template<typename Tag, typename Args, long N> |
122 | struct is_callable<proto::expr<Tag, Args, N> > |
123 | : mpl::false_ |
124 | {}; |
125 | |
126 | // work around GCC bug |
127 | template<typename Tag, typename Args, long N> |
128 | struct is_callable<proto::basic_expr<Tag, Args, N> > |
129 | : mpl::false_ |
130 | {}; |
131 | #endif |
132 | |
133 | namespace detail |
134 | { |
135 | template<typename T, typename Void /*= void*/> |
136 | struct is_transform_ |
137 | : mpl::false_ |
138 | {}; |
139 | |
140 | template<typename T> |
141 | struct is_transform_<T, typename T::proto_is_transform_> |
142 | : mpl::true_ |
143 | {}; |
144 | } |
145 | |
146 | /// \brief Boolean metafunction which detects whether a type is |
147 | /// a PrimitiveTransform type or not. |
148 | /// |
149 | /// <tt>is_transform\<\></tt> is used by the <tt>call\<\></tt> transform |
150 | /// to determine whether the function types <tt>R()</tt>, <tt>R(A1)</tt>, |
151 | /// and <tt>R(A1, A2)</tt> should be passed the expression, state and data |
152 | /// parameters (as needed). |
153 | /// |
154 | /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt> |
155 | /// is computed as follows: |
156 | /// |
157 | /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef |
158 | /// for \c void, <tt>is_transform\<T\>::value</tt> is \c true. (Note: this is |
159 | /// the case for any type that derives from an instantiation of \c proto::transform.) |
160 | /// \li Otherwise, <tt>is_transform\<T\>::value</tt> is \c false. |
161 | template<typename T> |
162 | struct is_transform |
163 | : proto::detail::is_transform_<T> |
164 | {}; |
165 | |
166 | namespace detail |
167 | { |
168 | template<typename T, typename Void /*= void*/> |
169 | struct is_aggregate_ |
170 | : is_pod<T> |
171 | {}; |
172 | |
173 | template<typename Tag, typename Args, long N> |
174 | struct is_aggregate_<proto::expr<Tag, Args, N>, void> |
175 | : mpl::true_ |
176 | {}; |
177 | |
178 | template<typename Tag, typename Args, long N> |
179 | struct is_aggregate_<proto::basic_expr<Tag, Args, N>, void> |
180 | : mpl::true_ |
181 | {}; |
182 | |
183 | template<typename T> |
184 | struct is_aggregate_<T, typename T::proto_is_aggregate_> |
185 | : mpl::true_ |
186 | {}; |
187 | } |
188 | |
189 | /// \brief A Boolean metafunction that indicates whether a type requires |
190 | /// aggregate initialization. |
191 | /// |
192 | /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform |
193 | /// to determine how to construct an object of some type \c T, given some |
194 | /// initialization arguments <tt>a0,a1,...aN</tt>. |
195 | /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of |
196 | /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise, |
197 | /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>. |
198 | template<typename T> |
199 | struct is_aggregate |
200 | : proto::detail::is_aggregate_<T> |
201 | {}; |
202 | |
203 | /// \brief A Boolean metafunction that indicates whether a given |
204 | /// type \c T is a Proto expression type. |
205 | /// |
206 | /// If \c T has a nested type \c proto_is_expr_ that is a typedef |
207 | /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this |
208 | /// is the case for <tt>proto::expr\<\></tt>, any type that is derived |
209 | /// from <tt>proto::extends\<\></tt> or that uses the |
210 | /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise, |
211 | /// <tt>is_expr\<T\>::value</tt> is \c false. |
212 | template<typename T, typename Void /* = void*/> |
213 | struct is_expr |
214 | : mpl::false_ |
215 | {}; |
216 | |
217 | /// \brief A Boolean metafunction that indicates whether a given |
218 | /// type \c T is a Proto expression type. |
219 | /// |
220 | /// If \c T has a nested type \c proto_is_expr_ that is a typedef |
221 | /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this |
222 | /// is the case for <tt>proto::expr\<\></tt>, any type that is derived |
223 | /// from <tt>proto::extends\<\></tt> or that uses the |
224 | /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise, |
225 | /// <tt>is_expr\<T\>::value</tt> is \c false. |
226 | template<typename T> |
227 | struct is_expr<T, typename T::proto_is_expr_> |
228 | : mpl::true_ |
229 | {}; |
230 | |
231 | template<typename T> |
232 | struct is_expr<T &, void> |
233 | : is_expr<T> |
234 | {}; |
235 | |
236 | /// \brief A metafunction that returns the tag type of a |
237 | /// Proto expression. |
238 | template<typename Expr> |
239 | struct tag_of |
240 | { |
241 | typedef typename Expr::proto_tag type; |
242 | }; |
243 | |
244 | template<typename Expr> |
245 | struct tag_of<Expr &> |
246 | { |
247 | typedef typename Expr::proto_tag type; |
248 | }; |
249 | |
250 | /// \brief A metafunction that returns the arity of a |
251 | /// Proto expression. |
252 | template<typename Expr> |
253 | struct arity_of |
254 | : Expr::proto_arity |
255 | {}; |
256 | |
257 | template<typename Expr> |
258 | struct arity_of<Expr &> |
259 | : Expr::proto_arity |
260 | {}; |
261 | |
262 | namespace result_of |
263 | { |
264 | /// \brief A metafunction that computes the return type of the \c as_expr() |
265 | /// function. |
266 | template<typename T, typename Domain /*= default_domain*/> |
267 | struct as_expr |
268 | { |
269 | typedef typename Domain::template as_expr<T>::result_type type; |
270 | }; |
271 | |
272 | /// \brief A metafunction that computes the return type of the \c as_child() |
273 | /// function. |
274 | template<typename T, typename Domain /*= default_domain*/> |
275 | struct as_child |
276 | { |
277 | typedef typename Domain::template as_child<T>::result_type type; |
278 | }; |
279 | |
280 | /// \brief A metafunction that returns the type of the Nth child |
281 | /// of a Proto expression, where N is an MPL Integral Constant. |
282 | /// |
283 | /// <tt>result_of::child\<Expr, N\></tt> is equivalent to |
284 | /// <tt>result_of::child_c\<Expr, N::value\></tt>. |
285 | template<typename Expr, typename N /* = mpl::long_<0>*/> |
286 | struct child |
287 | : child_c<Expr, N::value> |
288 | {}; |
289 | |
290 | /// \brief A metafunction that returns the type of the value |
291 | /// of a terminal Proto expression. |
292 | /// |
293 | template<typename Expr> |
294 | struct value |
295 | { |
296 | /// Verify that we are actually operating on a terminal |
297 | BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); |
298 | |
299 | /// The raw type of the Nth child as it is stored within |
300 | /// \c Expr. This may be a value or a reference |
301 | typedef typename Expr::proto_child0 value_type; |
302 | |
303 | /// The "value" type of the child, suitable for storage by value, |
304 | /// computed as follows: |
305 | /// \li <tt>T const(&)[N]</tt> becomes <tt>T[N]</tt> |
306 | /// \li <tt>T[N]</tt> becomes <tt>T[N]</tt> |
307 | /// \li <tt>T(&)[N]</tt> becomes <tt>T[N]</tt> |
308 | /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> |
309 | /// \li <tt>T const &</tt> becomes <tt>T</tt> |
310 | /// \li <tt>T &</tt> becomes <tt>T</tt> |
311 | /// \li <tt>T</tt> becomes <tt>T</tt> |
312 | typedef typename detail::term_traits<typename Expr::proto_child0>::value_type type; |
313 | }; |
314 | |
315 | template<typename Expr> |
316 | struct value<Expr &> |
317 | { |
318 | /// Verify that we are actually operating on a terminal |
319 | BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); |
320 | |
321 | /// The raw type of the Nth child as it is stored within |
322 | /// \c Expr. This may be a value or a reference |
323 | typedef typename Expr::proto_child0 value_type; |
324 | |
325 | /// The "reference" type of the child, suitable for storage by |
326 | /// reference, computed as follows: |
327 | /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt> |
328 | /// \li <tt>T[N]</tt> becomes <tt>T(&)[N]</tt> |
329 | /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt> |
330 | /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> |
331 | /// \li <tt>T const &</tt> becomes <tt>T const &</tt> |
332 | /// \li <tt>T &</tt> becomes <tt>T &</tt> |
333 | /// \li <tt>T</tt> becomes <tt>T &</tt> |
334 | typedef typename detail::term_traits<typename Expr::proto_child0>::reference type; |
335 | }; |
336 | |
337 | template<typename Expr> |
338 | struct value<Expr const &> |
339 | { |
340 | /// Verify that we are actually operating on a terminal |
341 | BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); |
342 | |
343 | /// The raw type of the Nth child as it is stored within |
344 | /// \c Expr. This may be a value or a reference |
345 | typedef typename Expr::proto_child0 value_type; |
346 | |
347 | /// The "const reference" type of the child, suitable for storage by |
348 | /// const reference, computed as follows: |
349 | /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt> |
350 | /// \li <tt>T[N]</tt> becomes <tt>T const(&)[N]</tt> |
351 | /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt> |
352 | /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt> |
353 | /// \li <tt>T const &</tt> becomes <tt>T const &</tt> |
354 | /// \li <tt>T &</tt> becomes <tt>T &</tt> |
355 | /// \li <tt>T</tt> becomes <tt>T const &</tt> |
356 | typedef typename detail::term_traits<typename Expr::proto_child0>::const_reference type; |
357 | }; |
358 | |
359 | /// \brief A metafunction that returns the type of the left child |
360 | /// of a binary Proto expression. |
361 | /// |
362 | /// <tt>result_of::left\<Expr\></tt> is equivalent to |
363 | /// <tt>result_of::child_c\<Expr, 0\></tt>. |
364 | template<typename Expr> |
365 | struct left |
366 | : child_c<Expr, 0> |
367 | {}; |
368 | |
369 | /// \brief A metafunction that returns the type of the right child |
370 | /// of a binary Proto expression. |
371 | /// |
372 | /// <tt>result_of::right\<Expr\></tt> is equivalent to |
373 | /// <tt>result_of::child_c\<Expr, 1\></tt>. |
374 | template<typename Expr> |
375 | struct right |
376 | : child_c<Expr, 1> |
377 | {}; |
378 | |
379 | } // namespace result_of |
380 | |
381 | /// \brief A metafunction for generating terminal expression types, |
382 | /// a grammar element for matching terminal expressions, and a |
383 | /// PrimitiveTransform that returns the current expression unchanged. |
384 | template<typename T> |
385 | struct terminal |
386 | : proto::transform<terminal<T>, int> |
387 | { |
388 | typedef proto::expr<proto::tag::terminal, term<T>, 0> type; |
389 | typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar; |
390 | |
391 | template<typename Expr, typename State, typename Data> |
392 | struct impl : transform_impl<Expr, State, Data> |
393 | { |
394 | typedef Expr result_type; |
395 | |
396 | /// \param e The current expression |
397 | /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true. |
398 | /// \return \c e |
399 | /// \throw nothrow |
400 | BOOST_FORCEINLINE |
401 | BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) |
402 | operator ()( |
403 | typename impl::expr_param e |
404 | , typename impl::state_param |
405 | , typename impl::data_param |
406 | ) const |
407 | { |
408 | return e; |
409 | } |
410 | }; |
411 | |
412 | /// INTERNAL ONLY |
413 | typedef proto::tag::terminal proto_tag; |
414 | /// INTERNAL ONLY |
415 | typedef T proto_child0; |
416 | }; |
417 | |
418 | /// \brief A metafunction for generating ternary conditional expression types, |
419 | /// a grammar element for matching ternary conditional expressions, and a |
420 | /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> |
421 | /// transform. |
422 | template<typename T, typename U, typename V> |
423 | struct if_else_ |
424 | : proto::transform<if_else_<T, U, V>, int> |
425 | { |
426 | typedef proto::expr<proto::tag::if_else_, list3<T, U, V>, 3> type; |
427 | typedef proto::basic_expr<proto::tag::if_else_, list3<T, U, V>, 3> proto_grammar; |
428 | |
429 | template<typename Expr, typename State, typename Data> |
430 | struct impl |
431 | : detail::pass_through_impl<if_else_, deduce_domain, Expr, State, Data> |
432 | {}; |
433 | |
434 | /// INTERNAL ONLY |
435 | typedef proto::tag::if_else_ proto_tag; |
436 | /// INTERNAL ONLY |
437 | typedef T proto_child0; |
438 | /// INTERNAL ONLY |
439 | typedef U proto_child1; |
440 | /// INTERNAL ONLY |
441 | typedef V proto_child2; |
442 | }; |
443 | |
444 | /// \brief A metafunction for generating nullary expression types with a |
445 | /// specified tag type, |
446 | /// a grammar element for matching nullary expressions, and a |
447 | /// PrimitiveTransform that returns the current expression unchanged. |
448 | /// |
449 | /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any |
450 | /// nullary expression. |
451 | template<typename Tag, typename T> |
452 | struct nullary_expr |
453 | : proto::transform<nullary_expr<Tag, T>, int> |
454 | { |
455 | typedef proto::expr<Tag, term<T>, 0> type; |
456 | typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar; |
457 | |
458 | template<typename Expr, typename State, typename Data> |
459 | struct impl : transform_impl<Expr, State, Data> |
460 | { |
461 | typedef Expr result_type; |
462 | |
463 | /// \param e The current expression |
464 | /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true. |
465 | /// \return \c e |
466 | /// \throw nothrow |
467 | BOOST_FORCEINLINE |
468 | BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) |
469 | operator ()( |
470 | typename impl::expr_param e |
471 | , typename impl::state_param |
472 | , typename impl::data_param |
473 | ) const |
474 | { |
475 | return e; |
476 | } |
477 | }; |
478 | |
479 | /// INTERNAL ONLY |
480 | typedef Tag proto_tag; |
481 | /// INTERNAL ONLY |
482 | typedef T proto_child0; |
483 | }; |
484 | |
485 | /// \brief A metafunction for generating unary expression types with a |
486 | /// specified tag type, |
487 | /// a grammar element for matching unary expressions, and a |
488 | /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> |
489 | /// transform. |
490 | /// |
491 | /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any |
492 | /// unary expression. |
493 | template<typename Tag, typename T> |
494 | struct unary_expr |
495 | : proto::transform<unary_expr<Tag, T>, int> |
496 | { |
497 | typedef proto::expr<Tag, list1<T>, 1> type; |
498 | typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar; |
499 | |
500 | template<typename Expr, typename State, typename Data> |
501 | struct impl |
502 | : detail::pass_through_impl<unary_expr, deduce_domain, Expr, State, Data> |
503 | {}; |
504 | |
505 | /// INTERNAL ONLY |
506 | typedef Tag proto_tag; |
507 | /// INTERNAL ONLY |
508 | typedef T proto_child0; |
509 | }; |
510 | |
511 | /// \brief A metafunction for generating binary expression types with a |
512 | /// specified tag type, |
513 | /// a grammar element for matching binary expressions, and a |
514 | /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt> |
515 | /// transform. |
516 | /// |
517 | /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any |
518 | /// binary expression. |
519 | template<typename Tag, typename T, typename U> |
520 | struct binary_expr |
521 | : proto::transform<binary_expr<Tag, T, U>, int> |
522 | { |
523 | typedef proto::expr<Tag, list2<T, U>, 2> type; |
524 | typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar; |
525 | |
526 | template<typename Expr, typename State, typename Data> |
527 | struct impl |
528 | : detail::pass_through_impl<binary_expr, deduce_domain, Expr, State, Data> |
529 | {}; |
530 | |
531 | /// INTERNAL ONLY |
532 | typedef Tag proto_tag; |
533 | /// INTERNAL ONLY |
534 | typedef T proto_child0; |
535 | /// INTERNAL ONLY |
536 | typedef U proto_child1; |
537 | }; |
538 | |
539 | #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op) \ |
540 | template<typename T> \ |
541 | struct Op \ |
542 | : proto::transform<Op<T>, int> \ |
543 | { \ |
544 | typedef proto::expr<proto::tag::Op, list1<T>, 1> type; \ |
545 | typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar; \ |
546 | \ |
547 | template<typename Expr, typename State, typename Data> \ |
548 | struct impl \ |
549 | : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data> \ |
550 | {}; \ |
551 | \ |
552 | typedef proto::tag::Op proto_tag; \ |
553 | typedef T proto_child0; \ |
554 | }; \ |
555 | /**/ |
556 | |
557 | #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op) \ |
558 | template<typename T, typename U> \ |
559 | struct Op \ |
560 | : proto::transform<Op<T, U>, int> \ |
561 | { \ |
562 | typedef proto::expr<proto::tag::Op, list2<T, U>, 2> type; \ |
563 | typedef proto::basic_expr<proto::tag::Op, list2<T, U>, 2> proto_grammar; \ |
564 | \ |
565 | template<typename Expr, typename State, typename Data> \ |
566 | struct impl \ |
567 | : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data> \ |
568 | {}; \ |
569 | \ |
570 | typedef proto::tag::Op proto_tag; \ |
571 | typedef T proto_child0; \ |
572 | typedef U proto_child1; \ |
573 | }; \ |
574 | /**/ |
575 | |
576 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus) |
577 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate) |
578 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference) |
579 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement) |
580 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of) |
581 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not) |
582 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc) |
583 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec) |
584 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc) |
585 | BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec) |
586 | |
587 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left) |
588 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right) |
589 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies) |
590 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides) |
591 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus) |
592 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus) |
593 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus) |
594 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less) |
595 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater) |
596 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal) |
597 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal) |
598 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to) |
599 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to) |
600 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or) |
601 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and) |
602 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or) |
603 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and) |
604 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor) |
605 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma) |
606 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr) |
607 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign) |
608 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign) |
609 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign) |
610 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign) |
611 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign) |
612 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign) |
613 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign) |
614 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign) |
615 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign) |
616 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign) |
617 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign) |
618 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript) |
619 | BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member) |
620 | |
621 | #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION |
622 | #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION |
623 | |
624 | #include <boost/proto/detail/traits.hpp> |
625 | |
626 | namespace functional |
627 | { |
628 | /// \brief A callable PolymorphicFunctionObject that is |
629 | /// equivalent to the \c as_expr() function. |
630 | template<typename Domain /* = default_domain*/> |
631 | struct as_expr |
632 | { |
633 | BOOST_PROTO_CALLABLE() |
634 | |
635 | template<typename Sig> |
636 | struct result; |
637 | |
638 | template<typename This, typename T> |
639 | struct result<This(T)> |
640 | { |
641 | typedef typename Domain::template as_expr<T>::result_type type; |
642 | }; |
643 | |
644 | template<typename This, typename T> |
645 | struct result<This(T &)> |
646 | { |
647 | typedef typename Domain::template as_expr<T>::result_type type; |
648 | }; |
649 | |
650 | /// \brief Wrap an object in a Proto terminal if it isn't a |
651 | /// Proto expression already. |
652 | /// \param t The object to wrap. |
653 | /// \return <tt>proto::as_expr\<Domain\>(t)</tt> |
654 | template<typename T> |
655 | BOOST_FORCEINLINE |
656 | typename add_const<typename result<as_expr(T &)>::type>::type |
657 | operator ()(T &t) const |
658 | { |
659 | return typename Domain::template as_expr<T>()(t); |
660 | } |
661 | |
662 | /// \overload |
663 | /// |
664 | template<typename T> |
665 | BOOST_FORCEINLINE |
666 | typename add_const<typename result<as_expr(T const &)>::type>::type |
667 | operator ()(T const &t) const |
668 | { |
669 | return typename Domain::template as_expr<T const>()(t); |
670 | } |
671 | |
672 | #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) |
673 | template<typename T, std::size_t N_> |
674 | BOOST_FORCEINLINE |
675 | typename add_const<typename result<as_expr(T (&)[N_])>::type>::type |
676 | operator ()(T (&t)[N_]) const |
677 | { |
678 | return typename Domain::template as_expr<T[N_]>()(t); |
679 | } |
680 | |
681 | template<typename T, std::size_t N_> |
682 | BOOST_FORCEINLINE |
683 | typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type |
684 | operator ()(T const (&t)[N_]) const |
685 | { |
686 | return typename Domain::template as_expr<T const[N_]>()(t); |
687 | } |
688 | #endif |
689 | }; |
690 | |
691 | /// \brief A callable PolymorphicFunctionObject that is |
692 | /// equivalent to the \c as_child() function. |
693 | template<typename Domain /* = default_domain*/> |
694 | struct as_child |
695 | { |
696 | BOOST_PROTO_CALLABLE() |
697 | |
698 | template<typename Sig> |
699 | struct result; |
700 | |
701 | template<typename This, typename T> |
702 | struct result<This(T)> |
703 | { |
704 | typedef typename Domain::template as_child<T>::result_type type; |
705 | }; |
706 | |
707 | template<typename This, typename T> |
708 | struct result<This(T &)> |
709 | { |
710 | typedef typename Domain::template as_child<T>::result_type type; |
711 | }; |
712 | |
713 | /// \brief Wrap an object in a Proto terminal if it isn't a |
714 | /// Proto expression already. |
715 | /// \param t The object to wrap. |
716 | /// \return <tt>proto::as_child\<Domain\>(t)</tt> |
717 | template<typename T> |
718 | BOOST_FORCEINLINE |
719 | typename add_const<typename result<as_child(T &)>::type>::type |
720 | operator ()(T &t) const |
721 | { |
722 | return typename Domain::template as_child<T>()(t); |
723 | } |
724 | |
725 | /// \overload |
726 | /// |
727 | template<typename T> |
728 | BOOST_FORCEINLINE |
729 | typename add_const<typename result<as_child(T const &)>::type>::type |
730 | operator ()(T const &t) const |
731 | { |
732 | return typename Domain::template as_child<T const>()(t); |
733 | } |
734 | }; |
735 | |
736 | /// \brief A callable PolymorphicFunctionObject that is |
737 | /// equivalent to the \c child_c() function. |
738 | template<long N> |
739 | struct child_c |
740 | { |
741 | BOOST_PROTO_CALLABLE() |
742 | |
743 | template<typename Sig> |
744 | struct result; |
745 | |
746 | template<typename This, typename Expr> |
747 | struct result<This(Expr)> |
748 | { |
749 | typedef typename result_of::child_c<Expr, N>::type type; |
750 | }; |
751 | |
752 | /// \brief Return the Nth child of the given expression. |
753 | /// \param expr The expression node. |
754 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true |
755 | /// \pre <tt>N \< Expr::proto_arity::value</tt> |
756 | /// \return <tt>proto::child_c\<N\>(expr)</tt> |
757 | /// \throw nothrow |
758 | template<typename Expr> |
759 | BOOST_FORCEINLINE |
760 | typename result_of::child_c<Expr &, N>::type |
761 | operator ()(Expr &e) const |
762 | { |
763 | return result_of::child_c<Expr &, N>::call(e); |
764 | } |
765 | |
766 | /// \overload |
767 | /// |
768 | template<typename Expr> |
769 | BOOST_FORCEINLINE |
770 | typename result_of::child_c<Expr const &, N>::type |
771 | operator ()(Expr const &e) const |
772 | { |
773 | return result_of::child_c<Expr const &, N>::call(e); |
774 | } |
775 | }; |
776 | |
777 | /// \brief A callable PolymorphicFunctionObject that is |
778 | /// equivalent to the \c child() function. |
779 | /// |
780 | /// A callable PolymorphicFunctionObject that is |
781 | /// equivalent to the \c child() function. \c N is required |
782 | /// to be an MPL Integral Constant. |
783 | template<typename N /* = mpl::long_<0>*/> |
784 | struct child |
785 | { |
786 | BOOST_PROTO_CALLABLE() |
787 | |
788 | template<typename Sig> |
789 | struct result; |
790 | |
791 | template<typename This, typename Expr> |
792 | struct result<This(Expr)> |
793 | { |
794 | typedef typename result_of::child<Expr, N>::type type; |
795 | }; |
796 | |
797 | /// \brief Return the Nth child of the given expression. |
798 | /// \param expr The expression node. |
799 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true |
800 | /// \pre <tt>N::value \< Expr::proto_arity::value</tt> |
801 | /// \return <tt>proto::child\<N\>(expr)</tt> |
802 | /// \throw nothrow |
803 | template<typename Expr> |
804 | BOOST_FORCEINLINE |
805 | typename result_of::child<Expr &, N>::type |
806 | operator ()(Expr &e) const |
807 | { |
808 | return result_of::child<Expr &, N>::call(e); |
809 | } |
810 | |
811 | /// \overload |
812 | /// |
813 | template<typename Expr> |
814 | BOOST_FORCEINLINE |
815 | typename result_of::child<Expr const &, N>::type |
816 | operator ()(Expr const &e) const |
817 | { |
818 | return result_of::child<Expr const &, N>::call(e); |
819 | } |
820 | }; |
821 | |
822 | /// \brief A callable PolymorphicFunctionObject that is |
823 | /// equivalent to the \c value() function. |
824 | struct value |
825 | { |
826 | BOOST_PROTO_CALLABLE() |
827 | |
828 | template<typename Sig> |
829 | struct result; |
830 | |
831 | template<typename This, typename Expr> |
832 | struct result<This(Expr)> |
833 | { |
834 | typedef typename result_of::value<Expr>::type type; |
835 | }; |
836 | |
837 | /// \brief Return the value of the given terminal expression. |
838 | /// \param expr The terminal expression node. |
839 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true |
840 | /// \pre <tt>0 == Expr::proto_arity::value</tt> |
841 | /// \return <tt>proto::value(expr)</tt> |
842 | /// \throw nothrow |
843 | template<typename Expr> |
844 | BOOST_FORCEINLINE |
845 | typename result_of::value<Expr &>::type |
846 | operator ()(Expr &e) const |
847 | { |
848 | return e.proto_base().child0; |
849 | } |
850 | |
851 | /// \overload |
852 | /// |
853 | template<typename Expr> |
854 | BOOST_FORCEINLINE |
855 | typename result_of::value<Expr const &>::type |
856 | operator ()(Expr const &e) const |
857 | { |
858 | return e.proto_base().child0; |
859 | } |
860 | }; |
861 | |
862 | /// \brief A callable PolymorphicFunctionObject that is |
863 | /// equivalent to the \c left() function. |
864 | struct left |
865 | { |
866 | BOOST_PROTO_CALLABLE() |
867 | |
868 | template<typename Sig> |
869 | struct result; |
870 | |
871 | template<typename This, typename Expr> |
872 | struct result<This(Expr)> |
873 | { |
874 | typedef typename result_of::left<Expr>::type type; |
875 | }; |
876 | |
877 | /// \brief Return the left child of the given binary expression. |
878 | /// \param expr The expression node. |
879 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true |
880 | /// \pre <tt>2 == Expr::proto_arity::value</tt> |
881 | /// \return <tt>proto::left(expr)</tt> |
882 | /// \throw nothrow |
883 | template<typename Expr> |
884 | BOOST_FORCEINLINE |
885 | typename result_of::left<Expr &>::type |
886 | operator ()(Expr &e) const |
887 | { |
888 | return e.proto_base().child0; |
889 | } |
890 | |
891 | /// \overload |
892 | /// |
893 | template<typename Expr> |
894 | BOOST_FORCEINLINE |
895 | typename result_of::left<Expr const &>::type |
896 | operator ()(Expr const &e) const |
897 | { |
898 | return e.proto_base().child0; |
899 | } |
900 | }; |
901 | |
902 | /// \brief A callable PolymorphicFunctionObject that is |
903 | /// equivalent to the \c right() function. |
904 | struct right |
905 | { |
906 | BOOST_PROTO_CALLABLE() |
907 | |
908 | template<typename Sig> |
909 | struct result; |
910 | |
911 | template<typename This, typename Expr> |
912 | struct result<This(Expr)> |
913 | { |
914 | typedef typename result_of::right<Expr>::type type; |
915 | }; |
916 | |
917 | /// \brief Return the right child of the given binary expression. |
918 | /// \param expr The expression node. |
919 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true |
920 | /// \pre <tt>2 == Expr::proto_arity::value</tt> |
921 | /// \return <tt>proto::right(expr)</tt> |
922 | /// \throw nothrow |
923 | template<typename Expr> |
924 | BOOST_FORCEINLINE |
925 | typename result_of::right<Expr &>::type |
926 | operator ()(Expr &e) const |
927 | { |
928 | return e.proto_base().child1; |
929 | } |
930 | |
931 | template<typename Expr> |
932 | BOOST_FORCEINLINE |
933 | typename result_of::right<Expr const &>::type |
934 | operator ()(Expr const &e) const |
935 | { |
936 | return e.proto_base().child1; |
937 | } |
938 | }; |
939 | |
940 | } |
941 | |
942 | /// \brief A function that wraps non-Proto expression types in Proto |
943 | /// terminals and leaves Proto expression types alone. |
944 | /// |
945 | /// The <tt>as_expr()</tt> function turns objects into Proto terminals if |
946 | /// they are not Proto expression types already. Non-Proto types are |
947 | /// held by value, if possible. Types which are already Proto types are |
948 | /// left alone and returned by reference. |
949 | /// |
950 | /// This function can be called either with an explicitly specified |
951 | /// \c Domain parameter (i.e., <tt>as_expr\<Domain\>(t)</tt>), or |
952 | /// without (i.e., <tt>as_expr(t)</tt>). If no domain is |
953 | /// specified, \c default_domain is assumed. |
954 | /// |
955 | /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is |
956 | /// returned unmodified, by reference. Otherwise, the argument is wrapped |
957 | /// in a Proto terminal expression node according to the following rules. |
958 | /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let |
959 | /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr() |
960 | /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>. |
961 | /// |
962 | /// \param t The object to wrap. |
963 | template<typename T> |
964 | BOOST_FORCEINLINE |
965 | typename add_const<typename result_of::as_expr<T, default_domain>::type>::type |
966 | as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) |
967 | { |
968 | return default_domain::as_expr<T>()(t); |
969 | } |
970 | |
971 | /// \overload |
972 | /// |
973 | template<typename T> |
974 | BOOST_FORCEINLINE |
975 | typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type |
976 | as_expr(T const &t) |
977 | { |
978 | return default_domain::as_expr<T const>()(t); |
979 | } |
980 | |
981 | /// \overload |
982 | /// |
983 | template<typename Domain, typename T> |
984 | BOOST_FORCEINLINE |
985 | typename add_const<typename result_of::as_expr<T, Domain>::type>::type |
986 | as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) |
987 | { |
988 | return typename Domain::template as_expr<T>()(t); |
989 | } |
990 | |
991 | /// \overload |
992 | /// |
993 | template<typename Domain, typename T> |
994 | BOOST_FORCEINLINE |
995 | typename add_const<typename result_of::as_expr<T const, Domain>::type>::type |
996 | as_expr(T const &t) |
997 | { |
998 | return typename Domain::template as_expr<T const>()(t); |
999 | } |
1000 | |
1001 | /// \brief A function that wraps non-Proto expression types in Proto |
1002 | /// terminals (by reference) and returns Proto expression types by |
1003 | /// reference |
1004 | /// |
1005 | /// The <tt>as_child()</tt> function turns objects into Proto terminals if |
1006 | /// they are not Proto expression types already. Non-Proto types are |
1007 | /// held by reference. Types which are already Proto types are simply |
1008 | /// returned as-is. |
1009 | /// |
1010 | /// This function can be called either with an explicitly specified |
1011 | /// \c Domain parameter (i.e., <tt>as_child\<Domain\>(t)</tt>), or |
1012 | /// without (i.e., <tt>as_child(t)</tt>). If no domain is |
1013 | /// specified, \c default_domain is assumed. |
1014 | /// |
1015 | /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is |
1016 | /// returned as-is. Otherwise, \c as_child() returns |
1017 | /// <tt>Domain()(terminal\<T &\>::type::make(t))</tt>. |
1018 | /// |
1019 | /// \param t The object to wrap. |
1020 | template<typename T> |
1021 | BOOST_FORCEINLINE |
1022 | typename add_const<typename result_of::as_child<T, default_domain>::type>::type |
1023 | as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) |
1024 | { |
1025 | return default_domain::as_child<T>()(t); |
1026 | } |
1027 | |
1028 | /// \overload |
1029 | /// |
1030 | template<typename T> |
1031 | BOOST_FORCEINLINE |
1032 | typename add_const<typename result_of::as_child<T const, default_domain>::type>::type |
1033 | as_child(T const &t) |
1034 | { |
1035 | return default_domain::as_child<T const>()(t); |
1036 | } |
1037 | |
1038 | /// \overload |
1039 | /// |
1040 | template<typename Domain, typename T> |
1041 | BOOST_FORCEINLINE |
1042 | typename add_const<typename result_of::as_child<T, Domain>::type>::type |
1043 | as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) |
1044 | { |
1045 | return typename Domain::template as_child<T>()(t); |
1046 | } |
1047 | |
1048 | /// \overload |
1049 | /// |
1050 | template<typename Domain, typename T> |
1051 | BOOST_FORCEINLINE |
1052 | typename add_const<typename result_of::as_child<T const, Domain>::type>::type |
1053 | as_child(T const &t) |
1054 | { |
1055 | return typename Domain::template as_child<T const>()(t); |
1056 | } |
1057 | |
1058 | /// \brief Return the Nth child of the specified Proto expression. |
1059 | /// |
1060 | /// Return the Nth child of the specified Proto expression. If |
1061 | /// \c N is not specified, as in \c child(expr), then \c N is assumed |
1062 | /// to be <tt>mpl::long_\<0\></tt>. The child is returned by |
1063 | /// reference. |
1064 | /// |
1065 | /// \param expr The Proto expression. |
1066 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. |
1067 | /// \pre \c N is an MPL Integral Constant. |
1068 | /// \pre <tt>N::value \< Expr::proto_arity::value</tt> |
1069 | /// \throw nothrow |
1070 | /// \return A reference to the Nth child |
1071 | template<typename N, typename Expr> |
1072 | BOOST_FORCEINLINE |
1073 | typename result_of::child<Expr &, N>::type |
1074 | child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) |
1075 | { |
1076 | return result_of::child<Expr &, N>::call(e); |
1077 | } |
1078 | |
1079 | /// \overload |
1080 | /// |
1081 | template<typename N, typename Expr> |
1082 | BOOST_FORCEINLINE |
1083 | typename result_of::child<Expr const &, N>::type |
1084 | child(Expr const &e) |
1085 | { |
1086 | return result_of::child<Expr const &, N>::call(e); |
1087 | } |
1088 | |
1089 | /// \overload |
1090 | /// |
1091 | template<typename Expr2> |
1092 | BOOST_FORCEINLINE |
1093 | typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::reference |
1094 | child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2)) |
1095 | { |
1096 | return expr2.proto_base().child0; |
1097 | } |
1098 | |
1099 | /// \overload |
1100 | /// |
1101 | template<typename Expr2> |
1102 | BOOST_FORCEINLINE |
1103 | typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::const_reference |
1104 | child(Expr2 const &expr2) |
1105 | { |
1106 | return expr2.proto_base().child0; |
1107 | } |
1108 | |
1109 | /// \brief Return the Nth child of the specified Proto expression. |
1110 | /// |
1111 | /// Return the Nth child of the specified Proto expression. The child |
1112 | /// is returned by reference. |
1113 | /// |
1114 | /// \param expr The Proto expression. |
1115 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. |
1116 | /// \pre <tt>N \< Expr::proto_arity::value</tt> |
1117 | /// \throw nothrow |
1118 | /// \return A reference to the Nth child |
1119 | template<long N, typename Expr> |
1120 | BOOST_FORCEINLINE |
1121 | typename result_of::child_c<Expr &, N>::type |
1122 | child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) |
1123 | { |
1124 | return result_of::child_c<Expr &, N>::call(e); |
1125 | } |
1126 | |
1127 | /// \overload |
1128 | /// |
1129 | template<long N, typename Expr> |
1130 | BOOST_FORCEINLINE |
1131 | typename result_of::child_c<Expr const &, N>::type |
1132 | child_c(Expr const &e) |
1133 | { |
1134 | return result_of::child_c<Expr const &, N>::call(e); |
1135 | } |
1136 | |
1137 | /// \brief Return the value stored within the specified Proto |
1138 | /// terminal expression. |
1139 | /// |
1140 | /// Return the value stored within the specified Proto |
1141 | /// terminal expression. The value is returned by |
1142 | /// reference. |
1143 | /// |
1144 | /// \param expr The Proto terminal expression. |
1145 | /// \pre <tt>N::value == 0</tt> |
1146 | /// \throw nothrow |
1147 | /// \return A reference to the terminal's value |
1148 | template<typename Expr> |
1149 | BOOST_FORCEINLINE |
1150 | typename result_of::value<Expr &>::type |
1151 | value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) |
1152 | { |
1153 | return e.proto_base().child0; |
1154 | } |
1155 | |
1156 | /// \overload |
1157 | /// |
1158 | template<typename Expr> |
1159 | BOOST_FORCEINLINE |
1160 | typename result_of::value<Expr const &>::type |
1161 | value(Expr const &e) |
1162 | { |
1163 | return e.proto_base().child0; |
1164 | } |
1165 | |
1166 | /// \brief Return the left child of the specified binary Proto |
1167 | /// expression. |
1168 | /// |
1169 | /// Return the left child of the specified binary Proto expression. The |
1170 | /// child is returned by reference. |
1171 | /// |
1172 | /// \param expr The Proto expression. |
1173 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. |
1174 | /// \pre <tt>2 == Expr::proto_arity::value</tt> |
1175 | /// \throw nothrow |
1176 | /// \return A reference to the left child |
1177 | template<typename Expr> |
1178 | BOOST_FORCEINLINE |
1179 | typename result_of::left<Expr &>::type |
1180 | left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) |
1181 | { |
1182 | return e.proto_base().child0; |
1183 | } |
1184 | |
1185 | /// \overload |
1186 | /// |
1187 | template<typename Expr> |
1188 | BOOST_FORCEINLINE |
1189 | typename result_of::left<Expr const &>::type |
1190 | left(Expr const &e) |
1191 | { |
1192 | return e.proto_base().child0; |
1193 | } |
1194 | |
1195 | /// \brief Return the right child of the specified binary Proto |
1196 | /// expression. |
1197 | /// |
1198 | /// Return the right child of the specified binary Proto expression. The |
1199 | /// child is returned by reference. |
1200 | /// |
1201 | /// \param expr The Proto expression. |
1202 | /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true. |
1203 | /// \pre <tt>2 == Expr::proto_arity::value</tt> |
1204 | /// \throw nothrow |
1205 | /// \return A reference to the right child |
1206 | template<typename Expr> |
1207 | BOOST_FORCEINLINE |
1208 | typename result_of::right<Expr &>::type |
1209 | right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) |
1210 | { |
1211 | return e.proto_base().child1; |
1212 | } |
1213 | |
1214 | /// \overload |
1215 | /// |
1216 | template<typename Expr> |
1217 | BOOST_FORCEINLINE |
1218 | typename result_of::right<Expr const &>::type |
1219 | right(Expr const &e) |
1220 | { |
1221 | return e.proto_base().child1; |
1222 | } |
1223 | |
1224 | /// INTERNAL ONLY |
1225 | /// |
1226 | template<typename Domain> |
1227 | struct is_callable<functional::as_expr<Domain> > |
1228 | : mpl::true_ |
1229 | {}; |
1230 | |
1231 | /// INTERNAL ONLY |
1232 | /// |
1233 | template<typename Domain> |
1234 | struct is_callable<functional::as_child<Domain> > |
1235 | : mpl::true_ |
1236 | {}; |
1237 | |
1238 | /// INTERNAL ONLY |
1239 | /// |
1240 | template<long N> |
1241 | struct is_callable<functional::child_c<N> > |
1242 | : mpl::true_ |
1243 | {}; |
1244 | |
1245 | /// INTERNAL ONLY |
1246 | /// |
1247 | template<typename N> |
1248 | struct is_callable<functional::child<N> > |
1249 | : mpl::true_ |
1250 | {}; |
1251 | |
1252 | }} |
1253 | |
1254 | #if defined(_MSC_VER) |
1255 | # pragma warning(pop) |
1256 | #endif |
1257 | |
1258 | #endif |
1259 | |