Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:19

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file default.hpp
0003 /// Definintion of default_context, a default evaluation context for
0004 /// proto::eval() that uses Boost.Typeof to deduce return types
0005 /// of the built-in operators.
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_CONTEXT_DEFAULT_HPP_EAN_01_08_2007
0012 #define BOOST_PROTO_CONTEXT_DEFAULT_HPP_EAN_01_08_2007
0013 
0014 #include <boost/config.hpp>
0015 #include <boost/preprocessor/arithmetic/add.hpp>
0016 #include <boost/preprocessor/arithmetic/sub.hpp>
0017 #include <boost/preprocessor/iteration/iterate.hpp>
0018 #include <boost/preprocessor/repetition/enum.hpp>
0019 #include <boost/preprocessor/repetition/enum_shifted.hpp>
0020 #include <boost/utility/result_of.hpp>
0021 #include <boost/type_traits/is_const.hpp>
0022 #include <boost/type_traits/is_function.hpp>
0023 #include <boost/type_traits/remove_reference.hpp>
0024 #include <boost/type_traits/is_member_pointer.hpp>
0025 #include <boost/type_traits/is_member_object_pointer.hpp>
0026 #include <boost/type_traits/is_member_function_pointer.hpp>
0027 #include <boost/proto/proto_fwd.hpp>
0028 #include <boost/proto/tags.hpp>
0029 #include <boost/proto/eval.hpp>
0030 #include <boost/proto/traits.hpp> // for proto::child_c()
0031 #include <boost/proto/detail/decltype.hpp>
0032 
0033 namespace boost { namespace proto
0034 {
0035 /// INTERNAL ONLY
0036 ///
0037 #define UNREF(x) typename boost::remove_reference<x>::type
0038 
0039     namespace context
0040     {
0041         template<
0042             typename Expr
0043           , typename Context
0044           , typename Tag        // = typename Expr::proto_tag
0045           , long Arity          // = Expr::proto_arity_c
0046         >
0047         struct default_eval
0048         {};
0049 
0050         template<typename Expr, typename Context>
0051         struct default_eval<Expr, Context, tag::terminal, 0>
0052         {
0053             typedef
0054                 typename proto::result_of::value<Expr &>::type
0055             result_type;
0056 
0057             result_type operator ()(Expr &expr, Context &) const
0058             {
0059                 return proto::value(expr);
0060             }
0061         };
0062 
0063         /// INTERNAL ONLY
0064         ///
0065     #define BOOST_PROTO_UNARY_DEFAULT_EVAL(OP, TAG, MAKE)                                       \
0066         template<typename Expr, typename Context>                                               \
0067         struct default_eval<Expr, Context, TAG, 1>                                              \
0068         {                                                                                       \
0069         private:                                                                                \
0070             typedef typename proto::result_of::child_c<Expr, 0>::type e0;                       \
0071             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;               \
0072         public:                                                                                 \
0073             BOOST_PROTO_DECLTYPE_(OP proto::detail::MAKE<r0>(), result_type)                    \
0074             result_type operator ()(Expr &expr, Context &ctx) const                             \
0075             {                                                                                   \
0076                 return OP proto::eval(proto::child_c<0>(expr), ctx);                            \
0077             }                                                                                   \
0078         };                                                                                      \
0079         /**/
0080 
0081         /// INTERNAL ONLY
0082         ///
0083     #define BOOST_PROTO_BINARY_DEFAULT_EVAL(OP, TAG, LMAKE, RMAKE)                              \
0084         template<typename Expr, typename Context>                                               \
0085         struct default_eval<Expr, Context, TAG, 2>                                              \
0086         {                                                                                       \
0087         private:                                                                                \
0088             typedef typename proto::result_of::child_c<Expr, 0>::type e0;                       \
0089             typedef typename proto::result_of::child_c<Expr, 1>::type e1;                       \
0090             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;               \
0091             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;               \
0092         public:                                                                                 \
0093             BOOST_PROTO_DECLTYPE_(                                                              \
0094                 proto::detail::LMAKE<r0>() OP proto::detail::RMAKE<r1>()                        \
0095               , result_type                                                                     \
0096             )                                                                                   \
0097             result_type operator ()(Expr &expr, Context &ctx) const                             \
0098             {                                                                                   \
0099                 return proto::eval(                                                             \
0100                     proto::child_c<0>(expr), ctx) OP proto::eval(proto::child_c<1>(expr)        \
0101                   , ctx                                                                         \
0102                 );                                                                              \
0103             }                                                                                   \
0104         };                                                                                      \
0105         /**/
0106 
0107         BOOST_PROTO_UNARY_DEFAULT_EVAL(+, proto::tag::unary_plus, make)
0108         BOOST_PROTO_UNARY_DEFAULT_EVAL(-, proto::tag::negate, make)
0109         BOOST_PROTO_UNARY_DEFAULT_EVAL(*, proto::tag::dereference, make)
0110         BOOST_PROTO_UNARY_DEFAULT_EVAL(~, proto::tag::complement, make)
0111         BOOST_PROTO_UNARY_DEFAULT_EVAL(&, proto::tag::address_of, make)
0112         BOOST_PROTO_UNARY_DEFAULT_EVAL(!, proto::tag::logical_not, make)
0113         BOOST_PROTO_UNARY_DEFAULT_EVAL(++, proto::tag::pre_inc, make_mutable)
0114         BOOST_PROTO_UNARY_DEFAULT_EVAL(--, proto::tag::pre_dec, make_mutable)
0115 
0116         BOOST_PROTO_BINARY_DEFAULT_EVAL(<<, proto::tag::shift_left, make_mutable, make)
0117         BOOST_PROTO_BINARY_DEFAULT_EVAL(>>, proto::tag::shift_right, make_mutable, make)
0118         BOOST_PROTO_BINARY_DEFAULT_EVAL(*, proto::tag::multiplies, make, make)
0119         BOOST_PROTO_BINARY_DEFAULT_EVAL(/, proto::tag::divides, make, make)
0120         BOOST_PROTO_BINARY_DEFAULT_EVAL(%, proto::tag::modulus, make, make)
0121         BOOST_PROTO_BINARY_DEFAULT_EVAL(+, proto::tag::plus, make, make)
0122         BOOST_PROTO_BINARY_DEFAULT_EVAL(-, proto::tag::minus, make, make)
0123         BOOST_PROTO_BINARY_DEFAULT_EVAL(<, proto::tag::less, make, make)
0124         BOOST_PROTO_BINARY_DEFAULT_EVAL(>, proto::tag::greater, make, make)
0125         BOOST_PROTO_BINARY_DEFAULT_EVAL(<=, proto::tag::less_equal, make, make)
0126         BOOST_PROTO_BINARY_DEFAULT_EVAL(>=, proto::tag::greater_equal, make, make)
0127         BOOST_PROTO_BINARY_DEFAULT_EVAL(==, proto::tag::equal_to, make, make)
0128         BOOST_PROTO_BINARY_DEFAULT_EVAL(!=, proto::tag::not_equal_to, make, make)
0129         BOOST_PROTO_BINARY_DEFAULT_EVAL(||, proto::tag::logical_or, make, make)
0130         BOOST_PROTO_BINARY_DEFAULT_EVAL(&&, proto::tag::logical_and, make, make)
0131         BOOST_PROTO_BINARY_DEFAULT_EVAL(&, proto::tag::bitwise_and, make, make)
0132         BOOST_PROTO_BINARY_DEFAULT_EVAL(|, proto::tag::bitwise_or, make, make)
0133         BOOST_PROTO_BINARY_DEFAULT_EVAL(^, proto::tag::bitwise_xor, make, make)
0134 
0135         BOOST_PROTO_BINARY_DEFAULT_EVAL(=, proto::tag::assign, make_mutable, make)
0136         BOOST_PROTO_BINARY_DEFAULT_EVAL(<<=, proto::tag::shift_left_assign, make_mutable, make)
0137         BOOST_PROTO_BINARY_DEFAULT_EVAL(>>=, proto::tag::shift_right_assign, make_mutable, make)
0138         BOOST_PROTO_BINARY_DEFAULT_EVAL(*=, proto::tag::multiplies_assign, make_mutable, make)
0139         BOOST_PROTO_BINARY_DEFAULT_EVAL(/=, proto::tag::divides_assign, make_mutable, make)
0140         BOOST_PROTO_BINARY_DEFAULT_EVAL(%=, proto::tag::modulus_assign, make_mutable, make)
0141         BOOST_PROTO_BINARY_DEFAULT_EVAL(+=, proto::tag::plus_assign, make_mutable, make)
0142         BOOST_PROTO_BINARY_DEFAULT_EVAL(-=, proto::tag::minus_assign, make_mutable, make)
0143         BOOST_PROTO_BINARY_DEFAULT_EVAL(&=, proto::tag::bitwise_and_assign, make_mutable, make)
0144         BOOST_PROTO_BINARY_DEFAULT_EVAL(|=, proto::tag::bitwise_or_assign, make_mutable, make)
0145         BOOST_PROTO_BINARY_DEFAULT_EVAL(^=, proto::tag::bitwise_xor_assign, make_mutable, make)
0146 
0147     #undef BOOST_PROTO_UNARY_DEFAULT_EVAL
0148     #undef BOOST_PROTO_BINARY_DEFAULT_EVAL
0149 
0150         /// INTERNAL ONLY
0151         template<typename Expr, typename Context>
0152         struct is_member_function_eval
0153           : is_member_function_pointer<
0154                 typename detail::uncvref<
0155                     typename proto::result_of::eval<
0156                         typename remove_reference<
0157                             typename proto::result_of::child_c<Expr, 1>::type
0158                         >::type
0159                       , Context
0160                     >::type
0161                 >::type
0162             >
0163         {};
0164 
0165         /// INTERNAL ONLY
0166         template<typename Expr, typename Context, bool IsMemFunCall>
0167         struct memfun_eval
0168         {
0169         private:
0170             typedef typename result_of::child_c<Expr, 0>::type e0;
0171             typedef typename result_of::child_c<Expr, 1>::type e1;
0172             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0173             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0174         public:
0175             typedef typename detail::mem_ptr_fun<r0, r1>::result_type result_type;
0176             result_type operator ()(Expr &expr, Context &ctx) const
0177             {
0178                 return detail::mem_ptr_fun<r0, r1>()(
0179                     proto::eval(proto::child_c<0>(expr), ctx)
0180                   , proto::eval(proto::child_c<1>(expr), ctx)
0181                 );
0182             }
0183         };
0184 
0185         /// INTERNAL ONLY
0186         template<typename Expr, typename Context>
0187         struct memfun_eval<Expr, Context, true>
0188         {
0189         private:
0190             typedef typename result_of::child_c<Expr, 0>::type e0;
0191             typedef typename result_of::child_c<Expr, 1>::type e1;
0192             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0193             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0194         public:
0195             typedef detail::memfun<r0, r1> result_type;
0196             result_type const operator ()(Expr &expr, Context &ctx) const
0197             {
0198                 return detail::memfun<r0, r1>(
0199                     proto::eval(proto::child_c<0>(expr), ctx)
0200                   , proto::eval(proto::child_c<1>(expr), ctx)
0201                 );
0202             }
0203         };
0204 
0205         template<typename Expr, typename Context>
0206         struct default_eval<Expr, Context, tag::mem_ptr, 2>
0207           : memfun_eval<Expr, Context, is_member_function_eval<Expr, Context>::value>
0208         {};
0209 
0210         // Handle post-increment specially.
0211         template<typename Expr, typename Context>
0212         struct default_eval<Expr, Context, proto::tag::post_inc, 1>
0213         {
0214         private:
0215             typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0216             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0217         public:
0218             BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() ++, result_type)
0219             result_type operator ()(Expr &expr, Context &ctx) const
0220             {
0221                 return proto::eval(proto::child_c<0>(expr), ctx) ++;
0222             }
0223         };
0224 
0225         // Handle post-decrement specially.
0226         template<typename Expr, typename Context>
0227         struct default_eval<Expr, Context, proto::tag::post_dec, 1>
0228         {
0229         private:
0230             typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0231             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0232         public:
0233             BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() --, result_type)
0234             result_type operator ()(Expr &expr, Context &ctx) const
0235             {
0236                 return proto::eval(proto::child_c<0>(expr), ctx) --;
0237             }
0238         };
0239 
0240         // Handle subscript specially.
0241         template<typename Expr, typename Context>
0242         struct default_eval<Expr, Context, proto::tag::subscript, 2>
0243         {
0244         private:
0245             typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0246             typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0247             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0248             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0249         public:
0250             BOOST_PROTO_DECLTYPE_(proto::detail::make_subscriptable<r0>()[proto::detail::make<r1>()], result_type)
0251             result_type operator ()(Expr &expr, Context &ctx) const
0252             {
0253                 return proto::eval(proto::child_c<0>(expr), ctx)[proto::eval(proto::child_c<1>(expr), ctx)];
0254             }
0255         };
0256 
0257         // Handle if_else_ specially.
0258         template<typename Expr, typename Context>
0259         struct default_eval<Expr, Context, proto::tag::if_else_, 3>
0260         {
0261         private:
0262             typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0263             typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0264             typedef typename proto::result_of::child_c<Expr, 2>::type e2;
0265             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0266             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0267             typedef typename proto::result_of::eval<UNREF(e2), Context>::type r2;
0268         public:
0269             BOOST_PROTO_DECLTYPE_(
0270                 proto::detail::make<r0>()
0271               ? proto::detail::make<r1>()
0272               : proto::detail::make<r2>()
0273               , result_type
0274             )
0275             result_type operator ()(Expr &expr, Context &ctx) const
0276             {
0277                 return proto::eval(proto::child_c<0>(expr), ctx)
0278                       ? proto::eval(proto::child_c<1>(expr), ctx)
0279                       : proto::eval(proto::child_c<2>(expr), ctx);
0280             }
0281         };
0282 
0283         // Handle comma specially.
0284         template<typename Expr, typename Context>
0285         struct default_eval<Expr, Context, proto::tag::comma, 2>
0286         {
0287         private:
0288             typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0289             typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0290             typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0291             typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0292         public:
0293             typedef typename proto::detail::comma_result<r0, r1>::type result_type;
0294             result_type operator ()(Expr &expr, Context &ctx) const
0295             {
0296                 return proto::eval(proto::child_c<0>(expr), ctx), proto::eval(proto::child_c<1>(expr), ctx);
0297             }
0298         };
0299 
0300         // Handle function specially
0301         #define BOOST_PROTO_DEFAULT_EVAL_TYPE(Z, N, DATA)                                       \
0302             typename proto::result_of::eval<                                                    \
0303                 typename remove_reference<                                                      \
0304                     typename proto::result_of::child_c<DATA, N>::type                           \
0305                 >::type                                                                         \
0306               , Context                                                                         \
0307             >::type                                                                             \
0308             /**/
0309 
0310         #define BOOST_PROTO_DEFAULT_EVAL(Z, N, DATA)                                            \
0311             proto::eval(proto::child_c<N>(DATA), context)                                       \
0312             /**/
0313 
0314         template<typename Expr, typename Context>
0315         struct default_eval<Expr, Context, proto::tag::function, 1>
0316         {
0317             typedef
0318                 typename proto::detail::result_of_fixup<
0319                     BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr)
0320                 >::type
0321             function_type;
0322 
0323             typedef
0324                 typename BOOST_PROTO_RESULT_OF<function_type()>::type
0325             result_type;
0326 
0327             result_type operator ()(Expr &expr, Context &context) const
0328             {
0329                 return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)();
0330             }
0331         };
0332 
0333         template<typename Expr, typename Context>
0334         struct default_eval<Expr, Context, proto::tag::function, 2>
0335         {
0336             typedef
0337                 typename proto::detail::result_of_fixup<
0338                     BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr)
0339                 >::type
0340             function_type;
0341 
0342             typedef
0343                 typename detail::result_of_<
0344                     function_type(BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 1, Expr))
0345                 >::type
0346             result_type;
0347 
0348             result_type operator ()(Expr &expr, Context &context) const
0349             {
0350                 return this->invoke(
0351                     expr
0352                   , context
0353                   , is_member_function_pointer<function_type>()
0354                   , is_member_object_pointer<function_type>()
0355                 );
0356             }
0357 
0358         private:
0359             result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::false_) const
0360             {
0361                 return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)(BOOST_PROTO_DEFAULT_EVAL(~, 1, expr));
0362             }
0363 
0364             result_type invoke(Expr &expr, Context &context, mpl::true_, mpl::false_) const
0365             {
0366                 BOOST_PROTO_USE_GET_POINTER();
0367                 typedef typename detail::class_member_traits<function_type>::class_type class_type;
0368                 return (
0369                     BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->* 
0370                     BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)
0371                 )();
0372             }
0373 
0374             result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::true_) const
0375             {
0376                 BOOST_PROTO_USE_GET_POINTER();
0377                 typedef typename detail::class_member_traits<function_type>::class_type class_type;
0378                 return (
0379                     BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->*
0380                     BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)
0381                 );
0382             }
0383         };
0384 
0385         // Additional specialization are generated by the preprocessor
0386         #include <boost/proto/context/detail/default_eval.hpp>
0387 
0388         #undef BOOST_PROTO_DEFAULT_EVAL_TYPE
0389         #undef BOOST_PROTO_DEFAULT_EVAL
0390 
0391         /// default_context
0392         ///
0393         struct default_context
0394         {
0395             /// default_context::eval
0396             ///
0397             template<typename Expr, typename ThisContext = default_context const>
0398             struct eval
0399               : default_eval<Expr, ThisContext>
0400             {};
0401         };
0402 
0403     } // namespace context
0404 
0405 }} // namespace boost::proto
0406 
0407 #undef UNREF
0408 
0409 #endif