1 ///////////////////////////////////////////////////////////////////////////////
3 /// Contains definitions for child\<\>, child_c\<\>, left\<\>,
4 /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(),
5 /// value(), left() and right().
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)
11 #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
12 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
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>
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
40 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
43 namespace boost { namespace proto
47 template<typename T, typename Void = void>
52 struct if_vararg<T, typename T::proto_is_vararg_>
56 template<typename T, typename Void = void>
62 struct is_callable2_<T, typename T::proto_is_callable_>
66 template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)>
73 /// \brief Boolean metafunction which detects whether a type is
74 /// a callable function object type or not.
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.
83 /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt>
84 /// is computed as follows:
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.
95 : proto::detail::is_callable_<T>
101 struct is_callable<proto::_>
108 struct is_callable<proto::callable>
114 template<typename PrimitiveTransform, typename X>
115 struct is_callable<proto::transform<PrimitiveTransform, X> >
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> >
126 // work around GCC bug
127 template<typename Tag, typename Args, long N>
128 struct is_callable<proto::basic_expr<Tag, Args, N> >
135 template<typename T, typename Void /*= void*/>
141 struct is_transform_<T, typename T::proto_is_transform_>
146 /// \brief Boolean metafunction which detects whether a type is
147 /// a PrimitiveTransform type or not.
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).
154 /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt>
155 /// is computed as follows:
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.
163 : proto::detail::is_transform_<T>
168 template<typename T, typename Void /*= void*/>
173 template<typename Tag, typename Args, long N>
174 struct is_aggregate_<proto::expr<Tag, Args, N>, void>
178 template<typename Tag, typename Args, long N>
179 struct is_aggregate_<proto::basic_expr<Tag, Args, N>, void>
184 struct is_aggregate_<T, typename T::proto_is_aggregate_>
189 /// \brief A Boolean metafunction that indicates whether a type requires
190 /// aggregate initialization.
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>.
200 : proto::detail::is_aggregate_<T>
203 /// \brief A Boolean metafunction that indicates whether a given
204 /// type \c T is a Proto expression type.
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*/>
217 /// \brief A Boolean metafunction that indicates whether a given
218 /// type \c T is a Proto expression type.
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.
227 struct is_expr<T, typename T::proto_is_expr_>
232 struct is_expr<T &, void>
236 /// \brief A metafunction that returns the tag type of a
237 /// Proto expression.
238 template<typename Expr>
241 typedef typename Expr::proto_tag type;
244 template<typename Expr>
245 struct tag_of<Expr &>
247 typedef typename Expr::proto_tag type;
250 /// \brief A metafunction that returns the arity of a
251 /// Proto expression.
252 template<typename Expr>
257 template<typename Expr>
258 struct arity_of<Expr &>
264 /// \brief A metafunction that computes the return type of the \c as_expr()
266 template<typename T, typename Domain /*= default_domain*/>
269 typedef typename Domain::template as_expr<T>::result_type type;
272 /// \brief A metafunction that computes the return type of the \c as_child()
274 template<typename T, typename Domain /*= default_domain*/>
277 typedef typename Domain::template as_child<T>::result_type type;
280 /// \brief A metafunction that returns the type of the Nth child
281 /// of a Proto expression, where N is an MPL Integral Constant.
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>*/>
287 : child_c<Expr, N::value>
290 /// \brief A metafunction that returns the type of the value
291 /// of a terminal Proto expression.
293 template<typename Expr>
296 /// Verify that we are actually operating on a terminal
297 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
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;
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;
315 template<typename Expr>
318 /// Verify that we are actually operating on a terminal
319 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
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;
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;
337 template<typename Expr>
338 struct value<Expr const &>
340 /// Verify that we are actually operating on a terminal
341 BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
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;
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;
359 /// \brief A metafunction that returns the type of the left child
360 /// of a binary Proto expression.
362 /// <tt>result_of::left\<Expr\></tt> is equivalent to
363 /// <tt>result_of::child_c\<Expr, 0\></tt>.
364 template<typename Expr>
369 /// \brief A metafunction that returns the type of the right child
370 /// of a binary Proto expression.
372 /// <tt>result_of::right\<Expr\></tt> is equivalent to
373 /// <tt>result_of::child_c\<Expr, 1\></tt>.
374 template<typename Expr>
379 } // namespace result_of
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.
386 : proto::transform<terminal<T>, int>
388 typedef proto::expr<proto::tag::terminal, term<T>, 0> type;
389 typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar;
391 template<typename Expr, typename State, typename Data>
392 struct impl : transform_impl<Expr, State, Data>
394 typedef Expr result_type;
396 /// \param e The current expression
397 /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true.
401 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
403 typename impl::expr_param e
404 , typename impl::state_param
405 , typename impl::data_param
413 typedef proto::tag::terminal proto_tag;
415 typedef T proto_child0;
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>
422 template<typename T, typename U, typename V>
424 : proto::transform<if_else_<T, U, V>, int>
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;
429 template<typename Expr, typename State, typename Data>
431 : detail::pass_through_impl<if_else_, deduce_domain, Expr, State, Data>
435 typedef proto::tag::if_else_ proto_tag;
437 typedef T proto_child0;
439 typedef U proto_child1;
441 typedef V proto_child2;
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.
449 /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any
450 /// nullary expression.
451 template<typename Tag, typename T>
453 : proto::transform<nullary_expr<Tag, T>, int>
455 typedef proto::expr<Tag, term<T>, 0> type;
456 typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar;
458 template<typename Expr, typename State, typename Data>
459 struct impl : transform_impl<Expr, State, Data>
461 typedef Expr result_type;
463 /// \param e The current expression
464 /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true.
468 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
470 typename impl::expr_param e
471 , typename impl::state_param
472 , typename impl::data_param
480 typedef Tag proto_tag;
482 typedef T proto_child0;
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>
491 /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any
492 /// unary expression.
493 template<typename Tag, typename T>
495 : proto::transform<unary_expr<Tag, T>, int>
497 typedef proto::expr<Tag, list1<T>, 1> type;
498 typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar;
500 template<typename Expr, typename State, typename Data>
502 : detail::pass_through_impl<unary_expr, deduce_domain, Expr, State, Data>
506 typedef Tag proto_tag;
508 typedef T proto_child0;
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>
517 /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any
518 /// binary expression.
519 template<typename Tag, typename T, typename U>
521 : proto::transform<binary_expr<Tag, T, U>, int>
523 typedef proto::expr<Tag, list2<T, U>, 2> type;
524 typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar;
526 template<typename Expr, typename State, typename Data>
528 : detail::pass_through_impl<binary_expr, deduce_domain, Expr, State, Data>
532 typedef Tag proto_tag;
534 typedef T proto_child0;
536 typedef U proto_child1;
539 #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op) \
540 template<typename T> \
542 : proto::transform<Op<T>, int> \
544 typedef proto::expr<proto::tag::Op, list1<T>, 1> type; \
545 typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar; \
547 template<typename Expr, typename State, typename Data> \
549 : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data> \
552 typedef proto::tag::Op proto_tag; \
553 typedef T proto_child0; \
557 #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op) \
558 template<typename T, typename U> \
560 : proto::transform<Op<T, U>, int> \
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; \
565 template<typename Expr, typename State, typename Data> \
567 : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data> \
570 typedef proto::tag::Op proto_tag; \
571 typedef T proto_child0; \
572 typedef U proto_child1; \
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)
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)
621 #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION
622 #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION
624 #include <boost/proto/detail/traits.hpp>
628 /// \brief A callable PolymorphicFunctionObject that is
629 /// equivalent to the \c as_expr() function.
630 template<typename Domain /* = default_domain*/>
633 BOOST_PROTO_CALLABLE()
635 template<typename Sig>
638 template<typename This, typename T>
639 struct result<This(T)>
641 typedef typename Domain::template as_expr<T>::result_type type;
644 template<typename This, typename T>
645 struct result<This(T &)>
647 typedef typename Domain::template as_expr<T>::result_type type;
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>
656 typename add_const<typename result<as_expr(T &)>::type>::type
657 operator ()(T &t) const
659 return typename Domain::template as_expr<T>()(t);
666 typename add_const<typename result<as_expr(T const &)>::type>::type
667 operator ()(T const &t) const
669 return typename Domain::template as_expr<T const>()(t);
672 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
673 template<typename T, std::size_t N_>
675 typename add_const<typename result<as_expr(T (&)[N_])>::type>::type
676 operator ()(T (&t)[N_]) const
678 return typename Domain::template as_expr<T[N_]>()(t);
681 template<typename T, std::size_t N_>
683 typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type
684 operator ()(T const (&t)[N_]) const
686 return typename Domain::template as_expr<T const[N_]>()(t);
691 /// \brief A callable PolymorphicFunctionObject that is
692 /// equivalent to the \c as_child() function.
693 template<typename Domain /* = default_domain*/>
696 BOOST_PROTO_CALLABLE()
698 template<typename Sig>
701 template<typename This, typename T>
702 struct result<This(T)>
704 typedef typename Domain::template as_child<T>::result_type type;
707 template<typename This, typename T>
708 struct result<This(T &)>
710 typedef typename Domain::template as_child<T>::result_type type;
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>
719 typename add_const<typename result<as_child(T &)>::type>::type
720 operator ()(T &t) const
722 return typename Domain::template as_child<T>()(t);
729 typename add_const<typename result<as_child(T const &)>::type>::type
730 operator ()(T const &t) const
732 return typename Domain::template as_child<T const>()(t);
736 /// \brief A callable PolymorphicFunctionObject that is
737 /// equivalent to the \c child_c() function.
741 BOOST_PROTO_CALLABLE()
743 template<typename Sig>
746 template<typename This, typename Expr>
747 struct result<This(Expr)>
749 typedef typename result_of::child_c<Expr, N>::type type;
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>
758 template<typename Expr>
760 typename result_of::child_c<Expr &, N>::type
761 operator ()(Expr &e) const
763 return result_of::child_c<Expr &, N>::call(e);
768 template<typename Expr>
770 typename result_of::child_c<Expr const &, N>::type
771 operator ()(Expr const &e) const
773 return result_of::child_c<Expr const &, N>::call(e);
777 /// \brief A callable PolymorphicFunctionObject that is
778 /// equivalent to the \c child() function.
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>*/>
786 BOOST_PROTO_CALLABLE()
788 template<typename Sig>
791 template<typename This, typename Expr>
792 struct result<This(Expr)>
794 typedef typename result_of::child<Expr, N>::type type;
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>
803 template<typename Expr>
805 typename result_of::child<Expr &, N>::type
806 operator ()(Expr &e) const
808 return result_of::child<Expr &, N>::call(e);
813 template<typename Expr>
815 typename result_of::child<Expr const &, N>::type
816 operator ()(Expr const &e) const
818 return result_of::child<Expr const &, N>::call(e);
822 /// \brief A callable PolymorphicFunctionObject that is
823 /// equivalent to the \c value() function.
826 BOOST_PROTO_CALLABLE()
828 template<typename Sig>
831 template<typename This, typename Expr>
832 struct result<This(Expr)>
834 typedef typename result_of::value<Expr>::type type;
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>
843 template<typename Expr>
845 typename result_of::value<Expr &>::type
846 operator ()(Expr &e) const
848 return e.proto_base().child0;
853 template<typename Expr>
855 typename result_of::value<Expr const &>::type
856 operator ()(Expr const &e) const
858 return e.proto_base().child0;
862 /// \brief A callable PolymorphicFunctionObject that is
863 /// equivalent to the \c left() function.
866 BOOST_PROTO_CALLABLE()
868 template<typename Sig>
871 template<typename This, typename Expr>
872 struct result<This(Expr)>
874 typedef typename result_of::left<Expr>::type type;
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>
883 template<typename Expr>
885 typename result_of::left<Expr &>::type
886 operator ()(Expr &e) const
888 return e.proto_base().child0;
893 template<typename Expr>
895 typename result_of::left<Expr const &>::type
896 operator ()(Expr const &e) const
898 return e.proto_base().child0;
902 /// \brief A callable PolymorphicFunctionObject that is
903 /// equivalent to the \c right() function.
906 BOOST_PROTO_CALLABLE()
908 template<typename Sig>
911 template<typename This, typename Expr>
912 struct result<This(Expr)>
914 typedef typename result_of::right<Expr>::type type;
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>
923 template<typename Expr>
925 typename result_of::right<Expr &>::type
926 operator ()(Expr &e) const
928 return e.proto_base().child1;
931 template<typename Expr>
933 typename result_of::right<Expr const &>::type
934 operator ()(Expr const &e) const
936 return e.proto_base().child1;
942 /// \brief A function that wraps non-Proto expression types in Proto
943 /// terminals and leaves Proto expression types alone.
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.
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.
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>.
962 /// \param t The object to wrap.
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))
968 return default_domain::as_expr<T>()(t);
975 typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type
978 return default_domain::as_expr<T const>()(t);
983 template<typename Domain, typename T>
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))
988 return typename Domain::template as_expr<T>()(t);
993 template<typename Domain, typename T>
995 typename add_const<typename result_of::as_expr<T const, Domain>::type>::type
998 return typename Domain::template as_expr<T const>()(t);
1001 /// \brief A function that wraps non-Proto expression types in Proto
1002 /// terminals (by reference) and returns Proto expression types by
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
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.
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>.
1019 /// \param t The object to wrap.
1020 template<typename T>
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))
1025 return default_domain::as_child<T>()(t);
1030 template<typename T>
1032 typename add_const<typename result_of::as_child<T const, default_domain>::type>::type
1033 as_child(T const &t)
1035 return default_domain::as_child<T const>()(t);
1040 template<typename Domain, typename T>
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))
1045 return typename Domain::template as_child<T>()(t);
1050 template<typename Domain, typename T>
1052 typename add_const<typename result_of::as_child<T const, Domain>::type>::type
1053 as_child(T const &t)
1055 return typename Domain::template as_child<T const>()(t);
1058 /// \brief Return the Nth child of the specified Proto expression.
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
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>
1070 /// \return A reference to the Nth child
1071 template<typename N, typename Expr>
1073 typename result_of::child<Expr &, N>::type
1074 child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1076 return result_of::child<Expr &, N>::call(e);
1081 template<typename N, typename Expr>
1083 typename result_of::child<Expr const &, N>::type
1084 child(Expr const &e)
1086 return result_of::child<Expr const &, N>::call(e);
1091 template<typename Expr2>
1093 typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::reference
1094 child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2))
1096 return expr2.proto_base().child0;
1101 template<typename Expr2>
1103 typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::const_reference
1104 child(Expr2 const &expr2)
1106 return expr2.proto_base().child0;
1109 /// \brief Return the Nth child of the specified Proto expression.
1111 /// Return the Nth child of the specified Proto expression. The child
1112 /// is returned by reference.
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>
1118 /// \return A reference to the Nth child
1119 template<long N, typename Expr>
1121 typename result_of::child_c<Expr &, N>::type
1122 child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1124 return result_of::child_c<Expr &, N>::call(e);
1129 template<long N, typename Expr>
1131 typename result_of::child_c<Expr const &, N>::type
1132 child_c(Expr const &e)
1134 return result_of::child_c<Expr const &, N>::call(e);
1137 /// \brief Return the value stored within the specified Proto
1138 /// terminal expression.
1140 /// Return the value stored within the specified Proto
1141 /// terminal expression. The value is returned by
1144 /// \param expr The Proto terminal expression.
1145 /// \pre <tt>N::value == 0</tt>
1147 /// \return A reference to the terminal's value
1148 template<typename Expr>
1150 typename result_of::value<Expr &>::type
1151 value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1153 return e.proto_base().child0;
1158 template<typename Expr>
1160 typename result_of::value<Expr const &>::type
1161 value(Expr const &e)
1163 return e.proto_base().child0;
1166 /// \brief Return the left child of the specified binary Proto
1169 /// Return the left child of the specified binary Proto expression. The
1170 /// child is returned by reference.
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>
1176 /// \return A reference to the left child
1177 template<typename Expr>
1179 typename result_of::left<Expr &>::type
1180 left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1182 return e.proto_base().child0;
1187 template<typename Expr>
1189 typename result_of::left<Expr const &>::type
1192 return e.proto_base().child0;
1195 /// \brief Return the right child of the specified binary Proto
1198 /// Return the right child of the specified binary Proto expression. The
1199 /// child is returned by reference.
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>
1205 /// \return A reference to the right child
1206 template<typename Expr>
1208 typename result_of::right<Expr &>::type
1209 right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1211 return e.proto_base().child1;
1216 template<typename Expr>
1218 typename result_of::right<Expr const &>::type
1219 right(Expr const &e)
1221 return e.proto_base().child1;
1226 template<typename Domain>
1227 struct is_callable<functional::as_expr<Domain> >
1233 template<typename Domain>
1234 struct is_callable<functional::as_child<Domain> >
1241 struct is_callable<functional::child_c<N> >
1247 template<typename N>
1248 struct is_callable<functional::child<N> >
1254 #if defined(_MSC_VER)
1255 # pragma warning(pop)