PageRenderTime 78ms CodeModel.GetById 20ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/proto/traits.hpp

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