1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file eval.hpp 3 /// Contains the eval() expression evaluator. 4 // 5 // Copyright 2008 Eric Niebler. Distributed under the Boost 6 // Software License, Version 1.0. (See accompanying file 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_PROTO_EVAL_HPP_EAN_03_29_2007 10 #define BOOST_PROTO_EVAL_HPP_EAN_03_29_2007 11 12 #include <boost/proto/proto_fwd.hpp> // BOOST_PROTO_CALLABLE 13 #include <boost/type_traits/remove_reference.hpp> 14 15 namespace boost { namespace proto 16 { 17 18 namespace result_of 19 { 20 /// \brief A metafunction for calculating the return type 21 /// of \c proto::eval() given a certain \c Expr and \c Context 22 /// types. 23 /// 24 /// \note The types \c Expr and \c Context should not be 25 /// reference types. They may be cv-qualified, but the 26 /// cv-qualification on the \c Context parameter is ignored. 27 template<typename Expr, typename Context> 28 struct eval 29 { 30 typedef typename Context::template eval<Expr>::result_type type; 31 }; 32 } 33 34 namespace functional 35 { 36 /// \brief A PolymorphicFunctionObject type for 37 /// evaluating a given Proto expression with a given 38 /// context. 39 struct eval 40 { 41 BOOST_PROTO_CALLABLE() 42 43 template<typename Sig> 44 struct result; 45 46 template<typename This, typename Expr, typename Context> 47 struct result<This(Expr, Context)> 48 { 49 typedef 50 typename proto::result_of::eval< 51 typename remove_reference<Expr>::type 52 , typename remove_reference<Context>::type 53 >::type 54 type; 55 }; 56 57 /// \brief Evaluate a given Proto expression with a given 58 /// context. 59 /// \param expr The Proto expression to evaluate 60 /// \param context The context in which the expression should be 61 /// evaluated. 62 /// \return <tt>typename Context::template eval<Expr>()(expr, context)</tt> 63 template<typename Expr, typename Context> 64 typename proto::result_of::eval<Expr, Context>::type operator ()boost::proto::functional::eval65 operator ()(Expr &e, Context &ctx) const 66 { 67 return typename Context::template eval<Expr>()(e, ctx); 68 } 69 70 /// \overload 71 /// 72 template<typename Expr, typename Context> 73 typename proto::result_of::eval<Expr, Context>::type operator ()boost::proto::functional::eval74 operator ()(Expr &e, Context const &ctx) const 75 { 76 return typename Context::template eval<Expr>()(e, ctx); 77 } 78 79 /// \overload 80 /// 81 template<typename Expr, typename Context> 82 typename proto::result_of::eval<Expr const, Context>::type operator ()boost::proto::functional::eval83 operator ()(Expr const &e, Context &ctx) const 84 { 85 return typename Context::template eval<Expr const>()(e, ctx); 86 } 87 88 /// \overload 89 /// 90 template<typename Expr, typename Context> 91 typename proto::result_of::eval<Expr const, Context>::type operator ()boost::proto::functional::eval92 operator ()(Expr const &e, Context const &ctx) const 93 { 94 return typename Context::template eval<Expr const>()(e, ctx); 95 } 96 }; 97 } 98 99 /// \brief Evaluate a given Proto expression with a given 100 /// context. 101 /// \param expr The Proto expression to evaluate 102 /// \param context The context in which the expression should be 103 /// evaluated. 104 /// \return <tt>typename Context::template eval<Expr>()(expr, context)</tt> 105 template<typename Expr, typename Context> 106 typename proto::result_of::eval<Expr, Context>::type eval(Expr & e,Context & ctx)107 eval(Expr &e, Context &ctx) 108 { 109 return typename Context::template eval<Expr>()(e, ctx); 110 } 111 112 /// \overload 113 /// 114 template<typename Expr, typename Context> 115 typename proto::result_of::eval<Expr, Context>::type eval(Expr & e,Context const & ctx)116 eval(Expr &e, Context const &ctx) 117 { 118 return typename Context::template eval<Expr>()(e, ctx); 119 } 120 121 /// \overload 122 /// 123 template<typename Expr, typename Context> 124 typename proto::result_of::eval<Expr const, Context>::type eval(Expr const & e,Context & ctx)125 eval(Expr const &e, Context &ctx) 126 { 127 return typename Context::template eval<Expr const>()(e, ctx); 128 } 129 130 /// \overload 131 /// 132 template<typename Expr, typename Context> 133 typename proto::result_of::eval<Expr const, Context>::type eval(Expr const & e,Context const & ctx)134 eval(Expr const &e, Context const &ctx) 135 { 136 return typename Context::template eval<Expr const>()(e, ctx); 137 } 138 }} 139 140 #endif 141