Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:07:37

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file traits.hpp
0003 /// Contains definitions for child\<\>, child_c\<\>, left\<\>,
0004 /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(),
0005 /// value(), left() and right().
0006 //
0007 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0008 //  Software License, Version 1.0. (See accompanying file
0009 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
0012 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
0013 
0014 #include <boost/config.hpp>
0015 #include <boost/detail/workaround.hpp>
0016 #include <boost/preprocessor/iteration/iterate.hpp>
0017 #include <boost/preprocessor/repetition/enum.hpp>
0018 #include <boost/preprocessor/repetition/enum_params.hpp>
0019 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0020 #include <boost/preprocessor/repetition/repeat.hpp>
0021 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
0022 #include <boost/preprocessor/facilities/intercept.hpp>
0023 #include <boost/preprocessor/arithmetic/sub.hpp>
0024 #include <boost/static_assert.hpp>
0025 #include <boost/mpl/bool.hpp>
0026 #include <boost/proto/detail/template_arity.hpp>
0027 #include <boost/type_traits/is_pod.hpp>
0028 #include <boost/type_traits/is_same.hpp>
0029 #include <boost/type_traits/add_const.hpp>
0030 #include <boost/proto/proto_fwd.hpp>
0031 #include <boost/proto/args.hpp>
0032 #include <boost/proto/domain.hpp>
0033 #include <boost/proto/transform/pass_through.hpp>
0034 
0035 #if defined(_MSC_VER)
0036 # pragma warning(push)
0037 # if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
0038 #  pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored
0039 # endif
0040 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
0041 #endif
0042 
0043 namespace boost { namespace proto
0044 {
0045     namespace detail
0046     {
0047         template<typename T, typename Void = void>
0048         struct if_vararg
0049         {};
0050 
0051         template<typename T>
0052         struct if_vararg<T, typename T::proto_is_vararg_>
0053           : T
0054         {};
0055 
0056         template<typename T, typename Void = void>
0057         struct is_callable2_
0058           : mpl::false_
0059         {};
0060 
0061         template<typename T>
0062         struct is_callable2_<T, typename T::proto_is_callable_>
0063           : mpl::true_
0064         {};
0065 
0066         template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)>
0067         struct is_callable_
0068           : is_callable2_<T>
0069         {};
0070 
0071     }
0072 
0073     /// \brief Boolean metafunction which detects whether a type is
0074     /// a callable function object type or not.
0075     ///
0076     /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform
0077     /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a
0078     /// callable transform or an object transform. (The former are evaluated
0079     /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If
0080     /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is
0081     /// a callable transform; otherwise, it is an object transform.
0082     ///
0083     /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt>
0084     /// is computed as follows:
0085     ///
0086     /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx
0087     /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt>
0088     /// is <tt>is_same\<YN, proto::callable\>::value</tt>.
0089     /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef
0090     /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is
0091     /// the case for any type that derives from \c proto::callable.)
0092     /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false.
0093     template<typename T>
0094     struct is_callable
0095       : proto::detail::is_callable_<T>
0096     {};
0097 
0098     /// INTERNAL ONLY
0099     ///
0100     template<>
0101     struct is_callable<proto::_>
0102       : mpl::true_
0103     {};
0104 
0105     /// INTERNAL ONLY
0106     ///
0107     template<>
0108     struct is_callable<proto::callable>
0109       : mpl::false_
0110     {};
0111 
0112     /// INTERNAL ONLY
0113     ///
0114     template<typename PrimitiveTransform, typename X>
0115     struct is_callable<proto::transform<PrimitiveTransform, X> >
0116       : mpl::false_
0117     {};
0118 
0119     #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0)
0120     // work around GCC bug
0121     template<typename Tag, typename Args, long N>
0122     struct is_callable<proto::expr<Tag, Args, N> >
0123       : mpl::false_
0124     {};
0125 
0126     // work around GCC bug
0127     template<typename Tag, typename Args, long N>
0128     struct is_callable<proto::basic_expr<Tag, Args, N> >
0129       : mpl::false_
0130     {};
0131     #endif
0132 
0133     namespace detail
0134     {
0135         template<typename T, typename Void /*= void*/>
0136         struct is_transform_
0137           : mpl::false_
0138         {};
0139 
0140         template<typename T>
0141         struct is_transform_<T, typename T::proto_is_transform_>
0142           : mpl::true_
0143         {};
0144     }
0145 
0146     /// \brief Boolean metafunction which detects whether a type is
0147     /// a PrimitiveTransform type or not.
0148     ///
0149     /// <tt>is_transform\<\></tt> is used by the <tt>call\<\></tt> transform
0150     /// to determine whether the function types <tt>R()</tt>, <tt>R(A1)</tt>,
0151     /// and <tt>R(A1, A2)</tt> should be passed the expression, state and data
0152     /// parameters (as needed).
0153     ///
0154     /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt>
0155     /// is computed as follows:
0156     ///
0157     /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef
0158     /// for \c void, <tt>is_transform\<T\>::value</tt> is \c true. (Note: this is
0159     /// the case for any type that derives from an instantiation of \c proto::transform.)
0160     /// \li Otherwise, <tt>is_transform\<T\>::value</tt> is \c false.
0161     template<typename T>
0162     struct is_transform
0163       : proto::detail::is_transform_<T>
0164     {};
0165 
0166     namespace detail
0167     {
0168         template<typename T, typename Void /*= void*/>
0169         struct is_aggregate_
0170           : is_pod<T>
0171         {};
0172 
0173         template<typename Tag, typename Args, long N>
0174         struct is_aggregate_<proto::expr<Tag, Args, N>, void>
0175           : mpl::true_
0176         {};
0177 
0178         template<typename Tag, typename Args, long N>
0179         struct is_aggregate_<proto::basic_expr<Tag, Args, N>, void>
0180           : mpl::true_
0181         {};
0182 
0183         template<typename T>
0184         struct is_aggregate_<T, typename T::proto_is_aggregate_>
0185           : mpl::true_
0186         {};
0187     }
0188 
0189     /// \brief A Boolean metafunction that indicates whether a type requires
0190     /// aggregate initialization.
0191     ///
0192     /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform
0193     /// to determine how to construct an object of some type \c T, given some
0194     /// initialization arguments <tt>a0,a1,...aN</tt>.
0195     /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of
0196     /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise,
0197     /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>.
0198     template<typename T>
0199     struct is_aggregate
0200       : proto::detail::is_aggregate_<T>
0201     {};
0202 
0203     /// \brief A Boolean metafunction that indicates whether a given
0204     /// type \c T is a Proto expression type.
0205     ///
0206     /// If \c T has a nested type \c proto_is_expr_ that is a typedef
0207     /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
0208     /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
0209     /// from <tt>proto::extends\<\></tt> or that uses the
0210     /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
0211     /// <tt>is_expr\<T\>::value</tt> is \c false.
0212     template<typename T, typename Void /* = void*/>
0213     struct is_expr
0214       : mpl::false_
0215     {};
0216 
0217     /// \brief A Boolean metafunction that indicates whether a given
0218     /// type \c T is a Proto expression type.
0219     ///
0220     /// If \c T has a nested type \c proto_is_expr_ that is a typedef
0221     /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
0222     /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
0223     /// from <tt>proto::extends\<\></tt> or that uses the
0224     /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
0225     /// <tt>is_expr\<T\>::value</tt> is \c false.
0226     template<typename T>
0227     struct is_expr<T, typename T::proto_is_expr_>
0228       : mpl::true_
0229     {};
0230             
0231     template<typename T>
0232     struct is_expr<T &, void>
0233       : is_expr<T>
0234     {};
0235 
0236     /// \brief A metafunction that returns the tag type of a
0237     /// Proto expression.
0238     template<typename Expr>
0239     struct tag_of
0240     {
0241         typedef typename Expr::proto_tag type;
0242     };
0243 
0244     template<typename Expr>
0245     struct tag_of<Expr &>
0246     {
0247         typedef typename Expr::proto_tag type;
0248     };
0249 
0250     /// \brief A metafunction that returns the arity of a
0251     /// Proto expression.
0252     template<typename Expr>
0253     struct arity_of
0254       : Expr::proto_arity
0255     {};
0256 
0257     template<typename Expr>
0258     struct arity_of<Expr &>
0259       : Expr::proto_arity
0260     {};
0261 
0262     namespace result_of
0263     {
0264         /// \brief A metafunction that computes the return type of the \c as_expr()
0265         /// function.
0266         template<typename T, typename Domain /*= default_domain*/>
0267         struct as_expr
0268         {
0269             typedef typename Domain::template as_expr<T>::result_type type;
0270         };
0271 
0272         /// \brief A metafunction that computes the return type of the \c as_child()
0273         /// function.
0274         template<typename T, typename Domain /*= default_domain*/>
0275         struct as_child
0276         {
0277             typedef typename Domain::template as_child<T>::result_type type;
0278         };
0279 
0280         /// \brief A metafunction that returns the type of the Nth child
0281         /// of a Proto expression, where N is an MPL Integral Constant.
0282         ///
0283         /// <tt>result_of::child\<Expr, N\></tt> is equivalent to
0284         /// <tt>result_of::child_c\<Expr, N::value\></tt>.
0285         template<typename Expr, typename N /* = mpl::long_<0>*/>
0286         struct child
0287           : child_c<Expr, N::value>
0288         {};
0289 
0290         /// \brief A metafunction that returns the type of the value
0291         /// of a terminal Proto expression.
0292         ///
0293         template<typename Expr>
0294         struct value
0295         {
0296             /// Verify that we are actually operating on a terminal
0297             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
0298 
0299             /// The raw type of the Nth child as it is stored within
0300             /// \c Expr. This may be a value or a reference
0301             typedef typename Expr::proto_child0 value_type;
0302 
0303             /// The "value" type of the child, suitable for storage by value,
0304             /// computed as follows:
0305             /// \li <tt>T const(&)[N]</tt> becomes <tt>T[N]</tt>
0306             /// \li <tt>T[N]</tt> becomes <tt>T[N]</tt>
0307             /// \li <tt>T(&)[N]</tt> becomes <tt>T[N]</tt>
0308             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
0309             /// \li <tt>T const &</tt> becomes <tt>T</tt>
0310             /// \li <tt>T &</tt> becomes <tt>T</tt>
0311             /// \li <tt>T</tt> becomes <tt>T</tt>
0312             typedef typename detail::term_traits<typename Expr::proto_child0>::value_type type;
0313         };
0314 
0315         template<typename Expr>
0316         struct value<Expr &>
0317         {
0318             /// Verify that we are actually operating on a terminal
0319             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
0320 
0321             /// The raw type of the Nth child as it is stored within
0322             /// \c Expr. This may be a value or a reference
0323             typedef typename Expr::proto_child0 value_type;
0324 
0325             /// The "reference" type of the child, suitable for storage by
0326             /// reference, computed as follows:
0327             /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
0328             /// \li <tt>T[N]</tt> becomes <tt>T(&)[N]</tt>
0329             /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
0330             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
0331             /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
0332             /// \li <tt>T &</tt> becomes <tt>T &</tt>
0333             /// \li <tt>T</tt> becomes <tt>T &</tt>
0334             typedef typename detail::term_traits<typename Expr::proto_child0>::reference type;
0335         };
0336 
0337         template<typename Expr>
0338         struct value<Expr const &>
0339         {
0340             /// Verify that we are actually operating on a terminal
0341             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
0342 
0343             /// The raw type of the Nth child as it is stored within
0344             /// \c Expr. This may be a value or a reference
0345             typedef typename Expr::proto_child0 value_type;
0346 
0347             /// The "const reference" type of the child, suitable for storage by
0348             /// const reference, computed as follows:
0349             /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
0350             /// \li <tt>T[N]</tt> becomes <tt>T const(&)[N]</tt>
0351             /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
0352             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
0353             /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
0354             /// \li <tt>T &</tt> becomes <tt>T &</tt>
0355             /// \li <tt>T</tt> becomes <tt>T const &</tt>
0356             typedef typename detail::term_traits<typename Expr::proto_child0>::const_reference type;
0357         };
0358 
0359         /// \brief A metafunction that returns the type of the left child
0360         /// of a binary Proto expression.
0361         ///
0362         /// <tt>result_of::left\<Expr\></tt> is equivalent to
0363         /// <tt>result_of::child_c\<Expr, 0\></tt>.
0364         template<typename Expr>
0365         struct left
0366           : child_c<Expr, 0>
0367         {};
0368 
0369         /// \brief A metafunction that returns the type of the right child
0370         /// of a binary Proto expression.
0371         ///
0372         /// <tt>result_of::right\<Expr\></tt> is equivalent to
0373         /// <tt>result_of::child_c\<Expr, 1\></tt>.
0374         template<typename Expr>
0375         struct right
0376           : child_c<Expr, 1>
0377         {};
0378 
0379     } // namespace result_of
0380 
0381     /// \brief A metafunction for generating terminal expression types,
0382     /// a grammar element for matching terminal expressions, and a
0383     /// PrimitiveTransform that returns the current expression unchanged.
0384     template<typename T>
0385     struct terminal
0386       : proto::transform<terminal<T>, int>
0387     {
0388         typedef proto::expr<proto::tag::terminal, term<T>, 0> type;
0389         typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar;
0390 
0391         template<typename Expr, typename State, typename Data>
0392         struct impl : transform_impl<Expr, State, Data>
0393         {
0394             typedef Expr result_type;
0395 
0396             /// \param e The current expression
0397             /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true.
0398             /// \return \c e
0399             /// \throw nothrow
0400             BOOST_FORCEINLINE
0401             BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
0402             operator ()(
0403                 typename impl::expr_param e
0404               , typename impl::state_param
0405               , typename impl::data_param
0406             ) const
0407             {
0408                 return e;
0409             }
0410         };
0411 
0412         /// INTERNAL ONLY
0413         typedef proto::tag::terminal proto_tag;
0414         /// INTERNAL ONLY
0415         typedef T proto_child0;
0416     };
0417 
0418     /// \brief A metafunction for generating ternary conditional expression types,
0419     /// a grammar element for matching ternary conditional expressions, and a
0420     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
0421     /// transform.
0422     template<typename T, typename U, typename V>
0423     struct if_else_
0424       : proto::transform<if_else_<T, U, V>, int>
0425     {
0426         typedef proto::expr<proto::tag::if_else_, list3<T, U, V>, 3> type;
0427         typedef proto::basic_expr<proto::tag::if_else_, list3<T, U, V>, 3> proto_grammar;
0428 
0429         template<typename Expr, typename State, typename Data>
0430         struct impl
0431           : detail::pass_through_impl<if_else_, deduce_domain, Expr, State, Data>
0432         {};
0433 
0434         /// INTERNAL ONLY
0435         typedef proto::tag::if_else_ proto_tag;
0436         /// INTERNAL ONLY
0437         typedef T proto_child0;
0438         /// INTERNAL ONLY
0439         typedef U proto_child1;
0440         /// INTERNAL ONLY
0441         typedef V proto_child2;
0442     };
0443 
0444     /// \brief A metafunction for generating nullary expression types with a
0445     /// specified tag type,
0446     /// a grammar element for matching nullary expressions, and a
0447     /// PrimitiveTransform that returns the current expression unchanged.
0448     ///
0449     /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any
0450     /// nullary expression.
0451     template<typename Tag, typename T>
0452     struct nullary_expr
0453       : proto::transform<nullary_expr<Tag, T>, int>
0454     {
0455         typedef proto::expr<Tag, term<T>, 0> type;
0456         typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar;
0457 
0458         template<typename Expr, typename State, typename Data>
0459         struct impl : transform_impl<Expr, State, Data>
0460         {
0461             typedef Expr result_type;
0462 
0463             /// \param e The current expression
0464             /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true.
0465             /// \return \c e
0466             /// \throw nothrow
0467             BOOST_FORCEINLINE
0468             BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
0469             operator ()(
0470                 typename impl::expr_param e
0471               , typename impl::state_param
0472               , typename impl::data_param
0473             ) const
0474             {
0475                 return e;
0476             }
0477         };
0478 
0479         /// INTERNAL ONLY
0480         typedef Tag proto_tag;
0481         /// INTERNAL ONLY
0482         typedef T proto_child0;
0483     };
0484 
0485     /// \brief A metafunction for generating unary expression types with a
0486     /// specified tag type,
0487     /// a grammar element for matching unary expressions, and a
0488     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
0489     /// transform.
0490     ///
0491     /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any
0492     /// unary expression.
0493     template<typename Tag, typename T>
0494     struct unary_expr
0495       : proto::transform<unary_expr<Tag, T>, int>
0496     {
0497         typedef proto::expr<Tag, list1<T>, 1> type;
0498         typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar;
0499 
0500         template<typename Expr, typename State, typename Data>
0501         struct impl
0502           : detail::pass_through_impl<unary_expr, deduce_domain, Expr, State, Data>
0503         {};
0504 
0505         /// INTERNAL ONLY
0506         typedef Tag proto_tag;
0507         /// INTERNAL ONLY
0508         typedef T proto_child0;
0509     };
0510 
0511     /// \brief A metafunction for generating binary expression types with a
0512     /// specified tag type,
0513     /// a grammar element for matching binary expressions, and a
0514     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
0515     /// transform.
0516     ///
0517     /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any
0518     /// binary expression.
0519     template<typename Tag, typename T, typename U>
0520     struct binary_expr
0521       : proto::transform<binary_expr<Tag, T, U>, int>
0522     {
0523         typedef proto::expr<Tag, list2<T, U>, 2> type;
0524         typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar;
0525 
0526         template<typename Expr, typename State, typename Data>
0527         struct impl
0528           : detail::pass_through_impl<binary_expr, deduce_domain, Expr, State, Data>
0529         {};
0530 
0531         /// INTERNAL ONLY
0532         typedef Tag proto_tag;
0533         /// INTERNAL ONLY
0534         typedef T proto_child0;
0535         /// INTERNAL ONLY
0536         typedef U proto_child1;
0537     };
0538 
0539 #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op)                                               \
0540     template<typename T>                                                                        \
0541     struct Op                                                                                   \
0542       : proto::transform<Op<T>, int>                                                            \
0543     {                                                                                           \
0544         typedef proto::expr<proto::tag::Op, list1<T>, 1> type;                                  \
0545         typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar;                   \
0546                                                                                                 \
0547         template<typename Expr, typename State, typename Data>                                  \
0548         struct impl                                                                             \
0549           : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data>                     \
0550         {};                                                                                     \
0551                                                                                                 \
0552         typedef proto::tag::Op proto_tag;                                                       \
0553         typedef T proto_child0;                                                                 \
0554     };                                                                                          \
0555     /**/
0556 
0557 #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op)                                              \
0558     template<typename T, typename U>                                                            \
0559     struct Op                                                                                   \
0560       : proto::transform<Op<T, U>, int>                                                         \
0561     {                                                                                           \
0562         typedef proto::expr<proto::tag::Op, list2<T, U>, 2> type;                               \
0563         typedef proto::basic_expr<proto::tag::Op, list2<T, U>, 2> proto_grammar;                \
0564                                                                                                 \
0565         template<typename Expr, typename State, typename Data>                                  \
0566         struct impl                                                                             \
0567           : detail::pass_through_impl<Op, deduce_domain, Expr, State, Data>                     \
0568         {};                                                                                     \
0569                                                                                                 \
0570         typedef proto::tag::Op proto_tag;                                                       \
0571         typedef T proto_child0;                                                                 \
0572         typedef U proto_child1;                                                                 \
0573     };                                                                                          \
0574     /**/
0575 
0576     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus)
0577     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate)
0578     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference)
0579     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement)
0580     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of)
0581     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not)
0582     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc)
0583     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec)
0584     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc)
0585     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec)
0586 
0587     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left)
0588     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right)
0589     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies)
0590     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides)
0591     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus)
0592     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus)
0593     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus)
0594     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less)
0595     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater)
0596     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal)
0597     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal)
0598     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to)
0599     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to)
0600     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or)
0601     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and)
0602     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or)
0603     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and)
0604     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor)
0605     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma)
0606     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr)
0607     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign)
0608     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign)
0609     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign)
0610     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign)
0611     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign)
0612     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign)
0613     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign)
0614     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign)
0615     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign)
0616     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign)
0617     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign)
0618     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript)
0619     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member)
0620 
0621     #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION
0622     #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION
0623 
0624     #include <boost/proto/detail/traits.hpp>
0625 
0626     namespace functional
0627     {
0628         /// \brief A callable PolymorphicFunctionObject that is
0629         /// equivalent to the \c as_expr() function.
0630         template<typename Domain   /* = default_domain*/>
0631         struct as_expr
0632         {
0633             BOOST_PROTO_CALLABLE()
0634 
0635             template<typename Sig>
0636             struct result;
0637 
0638             template<typename This, typename T>
0639             struct result<This(T)>
0640             {
0641                 typedef typename Domain::template as_expr<T>::result_type type;
0642             };
0643 
0644             template<typename This, typename T>
0645             struct result<This(T &)>
0646             {
0647                 typedef typename Domain::template as_expr<T>::result_type type;
0648             };
0649 
0650             /// \brief Wrap an object in a Proto terminal if it isn't a
0651             /// Proto expression already.
0652             /// \param t The object to wrap.
0653             /// \return <tt>proto::as_expr\<Domain\>(t)</tt>
0654             template<typename T>
0655             BOOST_FORCEINLINE
0656             typename add_const<typename result<as_expr(T &)>::type>::type
0657             operator ()(T &t) const
0658             {
0659                 return typename Domain::template as_expr<T>()(t);
0660             }
0661 
0662             /// \overload
0663             ///
0664             template<typename T>
0665             BOOST_FORCEINLINE
0666             typename add_const<typename result<as_expr(T const &)>::type>::type
0667             operator ()(T const &t) const
0668             {
0669                 return typename Domain::template as_expr<T const>()(t);
0670             }
0671 
0672             #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
0673             template<typename T, std::size_t N_>
0674             BOOST_FORCEINLINE
0675             typename add_const<typename result<as_expr(T (&)[N_])>::type>::type
0676             operator ()(T (&t)[N_]) const
0677             {
0678                 return typename Domain::template as_expr<T[N_]>()(t);
0679             }
0680 
0681             template<typename T, std::size_t N_>
0682             BOOST_FORCEINLINE
0683             typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type
0684             operator ()(T const (&t)[N_]) const
0685             {
0686                 return typename Domain::template as_expr<T const[N_]>()(t);
0687             }
0688             #endif
0689         };
0690 
0691         /// \brief A callable PolymorphicFunctionObject that is
0692         /// equivalent to the \c as_child() function.
0693         template<typename Domain   /* = default_domain*/>
0694         struct as_child
0695         {
0696             BOOST_PROTO_CALLABLE()
0697 
0698             template<typename Sig>
0699             struct result;
0700 
0701             template<typename This, typename T>
0702             struct result<This(T)>
0703             {
0704                 typedef typename Domain::template as_child<T>::result_type type;
0705             };
0706 
0707             template<typename This, typename T>
0708             struct result<This(T &)>
0709             {
0710                 typedef typename Domain::template as_child<T>::result_type type;
0711             };
0712 
0713             /// \brief Wrap an object in a Proto terminal if it isn't a
0714             /// Proto expression already.
0715             /// \param t The object to wrap.
0716             /// \return <tt>proto::as_child\<Domain\>(t)</tt>
0717             template<typename T>
0718             BOOST_FORCEINLINE
0719             typename add_const<typename result<as_child(T &)>::type>::type
0720             operator ()(T &t) const
0721             {
0722                 return typename Domain::template as_child<T>()(t);
0723             }
0724 
0725             /// \overload
0726             ///
0727             template<typename T>
0728             BOOST_FORCEINLINE
0729             typename add_const<typename result<as_child(T const &)>::type>::type
0730             operator ()(T const &t) const
0731             {
0732                 return typename Domain::template as_child<T const>()(t);
0733             }
0734         };
0735 
0736         /// \brief A callable PolymorphicFunctionObject that is
0737         /// equivalent to the \c child_c() function.
0738         template<long N>
0739         struct child_c
0740         {
0741             BOOST_PROTO_CALLABLE()
0742 
0743             template<typename Sig>
0744             struct result;
0745 
0746             template<typename This, typename Expr>
0747             struct result<This(Expr)>
0748             {
0749                 typedef typename result_of::child_c<Expr, N>::type type;
0750             };
0751 
0752             /// \brief Return the Nth child of the given expression.
0753             /// \param expr The expression node.
0754             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
0755             /// \pre <tt>N \< Expr::proto_arity::value</tt>
0756             /// \return <tt>proto::child_c\<N\>(expr)</tt>
0757             /// \throw nothrow
0758             template<typename Expr>
0759             BOOST_FORCEINLINE
0760             typename result_of::child_c<Expr &, N>::type
0761             operator ()(Expr &e) const
0762             {
0763                 return result_of::child_c<Expr &, N>::call(e);
0764             }
0765 
0766             /// \overload
0767             ///
0768             template<typename Expr>
0769             BOOST_FORCEINLINE
0770             typename result_of::child_c<Expr const &, N>::type
0771             operator ()(Expr const &e) const
0772             {
0773                 return result_of::child_c<Expr const &, N>::call(e);
0774             }
0775         };
0776 
0777         /// \brief A callable PolymorphicFunctionObject that is
0778         /// equivalent to the \c child() function.
0779         ///
0780         /// A callable PolymorphicFunctionObject that is
0781         /// equivalent to the \c child() function. \c N is required
0782         /// to be an MPL Integral Constant.
0783         template<typename N /* = mpl::long_<0>*/>
0784         struct child
0785         {
0786             BOOST_PROTO_CALLABLE()
0787 
0788             template<typename Sig>
0789             struct result;
0790 
0791             template<typename This, typename Expr>
0792             struct result<This(Expr)>
0793             {
0794                 typedef typename result_of::child<Expr, N>::type type;
0795             };
0796 
0797             /// \brief Return the Nth child of the given expression.
0798             /// \param expr The expression node.
0799             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
0800             /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
0801             /// \return <tt>proto::child\<N\>(expr)</tt>
0802             /// \throw nothrow
0803             template<typename Expr>
0804             BOOST_FORCEINLINE
0805             typename result_of::child<Expr &, N>::type
0806             operator ()(Expr &e) const
0807             {
0808                 return result_of::child<Expr &, N>::call(e);
0809             }
0810 
0811             /// \overload
0812             ///
0813             template<typename Expr>
0814             BOOST_FORCEINLINE
0815             typename result_of::child<Expr const &, N>::type
0816             operator ()(Expr const &e) const
0817             {
0818                 return result_of::child<Expr const &, N>::call(e);
0819             }
0820         };
0821 
0822         /// \brief A callable PolymorphicFunctionObject that is
0823         /// equivalent to the \c value() function.
0824         struct value
0825         {
0826             BOOST_PROTO_CALLABLE()
0827 
0828             template<typename Sig>
0829             struct result;
0830 
0831             template<typename This, typename Expr>
0832             struct result<This(Expr)>
0833             {
0834                 typedef typename result_of::value<Expr>::type type;
0835             };
0836 
0837             /// \brief Return the value of the given terminal expression.
0838             /// \param expr The terminal expression node.
0839             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
0840             /// \pre <tt>0 == Expr::proto_arity::value</tt>
0841             /// \return <tt>proto::value(expr)</tt>
0842             /// \throw nothrow
0843             template<typename Expr>
0844             BOOST_FORCEINLINE
0845             typename result_of::value<Expr &>::type
0846             operator ()(Expr &e) const
0847             {
0848                 return e.proto_base().child0;
0849             }
0850 
0851             /// \overload
0852             ///
0853             template<typename Expr>
0854             BOOST_FORCEINLINE
0855             typename result_of::value<Expr const &>::type
0856             operator ()(Expr const &e) const
0857             {
0858                 return e.proto_base().child0;
0859             }
0860         };
0861 
0862         /// \brief A callable PolymorphicFunctionObject that is
0863         /// equivalent to the \c left() function.
0864         struct left
0865         {
0866             BOOST_PROTO_CALLABLE()
0867 
0868             template<typename Sig>
0869             struct result;
0870 
0871             template<typename This, typename Expr>
0872             struct result<This(Expr)>
0873             {
0874                 typedef typename result_of::left<Expr>::type type;
0875             };
0876 
0877             /// \brief Return the left child of the given binary expression.
0878             /// \param expr The expression node.
0879             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
0880             /// \pre <tt>2 == Expr::proto_arity::value</tt>
0881             /// \return <tt>proto::left(expr)</tt>
0882             /// \throw nothrow
0883             template<typename Expr>
0884             BOOST_FORCEINLINE
0885             typename result_of::left<Expr &>::type
0886             operator ()(Expr &e) const
0887             {
0888                 return e.proto_base().child0;
0889             }
0890 
0891             /// \overload
0892             ///
0893             template<typename Expr>
0894             BOOST_FORCEINLINE
0895             typename result_of::left<Expr const &>::type
0896             operator ()(Expr const &e) const
0897             {
0898                 return e.proto_base().child0;
0899             }
0900         };
0901 
0902         /// \brief A callable PolymorphicFunctionObject that is
0903         /// equivalent to the \c right() function.
0904         struct right
0905         {
0906             BOOST_PROTO_CALLABLE()
0907 
0908             template<typename Sig>
0909             struct result;
0910 
0911             template<typename This, typename Expr>
0912             struct result<This(Expr)>
0913             {
0914                 typedef typename result_of::right<Expr>::type type;
0915             };
0916 
0917             /// \brief Return the right child of the given binary expression.
0918             /// \param expr The expression node.
0919             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
0920             /// \pre <tt>2 == Expr::proto_arity::value</tt>
0921             /// \return <tt>proto::right(expr)</tt>
0922             /// \throw nothrow
0923             template<typename Expr>
0924             BOOST_FORCEINLINE
0925             typename result_of::right<Expr &>::type
0926             operator ()(Expr &e) const
0927             {
0928                 return e.proto_base().child1;
0929             }
0930 
0931             template<typename Expr>
0932             BOOST_FORCEINLINE
0933             typename result_of::right<Expr const &>::type
0934             operator ()(Expr const &e) const
0935             {
0936                 return e.proto_base().child1;
0937             }
0938         };
0939 
0940     }
0941 
0942     /// \brief A function that wraps non-Proto expression types in Proto
0943     /// terminals and leaves Proto expression types alone.
0944     ///
0945     /// The <tt>as_expr()</tt> function turns objects into Proto terminals if
0946     /// they are not Proto expression types already. Non-Proto types are
0947     /// held by value, if possible. Types which are already Proto types are
0948     /// left alone and returned by reference.
0949     ///
0950     /// This function can be called either with an explicitly specified
0951     /// \c Domain parameter (i.e., <tt>as_expr\<Domain\>(t)</tt>), or
0952     /// without (i.e., <tt>as_expr(t)</tt>). If no domain is
0953     /// specified, \c default_domain is assumed.
0954     ///
0955     /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
0956     /// returned unmodified, by reference. Otherwise, the argument is wrapped
0957     /// in a Proto terminal expression node according to the following rules.
0958     /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let
0959     /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr()
0960     /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>.
0961     ///
0962     /// \param t The object to wrap.
0963     template<typename T>
0964     BOOST_FORCEINLINE
0965     typename add_const<typename result_of::as_expr<T, default_domain>::type>::type
0966     as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
0967     {
0968         return default_domain::as_expr<T>()(t);
0969     }
0970 
0971     /// \overload
0972     ///
0973     template<typename T>
0974     BOOST_FORCEINLINE
0975     typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type
0976     as_expr(T const &t)
0977     {
0978         return default_domain::as_expr<T const>()(t);
0979     }
0980 
0981     /// \overload
0982     ///
0983     template<typename Domain, typename T>
0984     BOOST_FORCEINLINE
0985     typename add_const<typename result_of::as_expr<T, Domain>::type>::type
0986     as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
0987     {
0988         return typename Domain::template as_expr<T>()(t);
0989     }
0990 
0991     /// \overload
0992     ///
0993     template<typename Domain, typename T>
0994     BOOST_FORCEINLINE
0995     typename add_const<typename result_of::as_expr<T const, Domain>::type>::type
0996     as_expr(T const &t)
0997     {
0998         return typename Domain::template as_expr<T const>()(t);
0999     }
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