1 /*============================================================================= 2 Copyright (c) 2005-2010 Joel de Guzman 3 Copyright (c) 2010 Eric Niebler 4 Copyright (c) 2010 Thomas Heller 5 Copyright (c) 2014 John Fletcher 6 7 Distributed under the Boost Software License, Version 1.0. (See accompanying 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 ==============================================================================*/ 10 #ifndef BOOST_PHOENIX_CORE_ACTOR_HPP 11 #define BOOST_PHOENIX_CORE_ACTOR_HPP 12 13 #include <boost/phoenix/core/limits.hpp> 14 15 #include <boost/is_placeholder.hpp> 16 #include <boost/mpl/identity.hpp> 17 #include <boost/mpl/eval_if.hpp> 18 #include <boost/phoenix/core/domain.hpp> 19 #include <boost/phoenix/core/environment.hpp> 20 #include <boost/phoenix/core/is_nullary.hpp> 21 #include <boost/phoenix/core/meta_grammar.hpp> 22 #include <boost/phoenix/support/iterate.hpp> 23 #include <boost/phoenix/support/vector.hpp> 24 #include <boost/proto/extends.hpp> 25 #include <boost/proto/make_expr.hpp> 26 #include <boost/utility/result_of.hpp> 27 #include <boost/mpl/void.hpp> 28 #include <cstring> 29 #ifndef BOOST_PHOENIX_NO_VARIADIC_ACTOR 30 # include <boost/mpl/if.hpp> 31 # include <boost/type_traits/is_reference.hpp> 32 # include <boost/phoenix/core/detail/index_sequence.hpp> 33 #endif 34 35 #ifdef BOOST_MSVC 36 #pragma warning(push) 37 #pragma warning(disable: 4522) // 'this' used in base member initializer list 38 #pragma warning(disable: 4510) // default constructor could not be generated 39 #pragma warning(disable: 4610) // can never be instantiated - user defined cons 40 #endif 41 42 namespace boost { namespace phoenix 43 { 44 template <typename Expr> 45 struct actor; 46 47 namespace detail 48 { 49 struct error_expecting_arguments 50 { 51 template <typename T> error_expecting_argumentsboost::phoenix::detail::error_expecting_arguments52 error_expecting_arguments(T const&) {} 53 }; 54 55 struct error_invalid_lambda_expr 56 { 57 template <typename T> error_invalid_lambda_exprboost::phoenix::detail::error_invalid_lambda_expr58 error_invalid_lambda_expr(T const&) {} 59 }; 60 61 template <typename T> 62 struct result_type_deduction_helper 63 { 64 typedef T const & type; 65 }; 66 67 template <typename T> 68 struct result_type_deduction_helper<T &> 69 { 70 typedef T & type; 71 }; 72 73 template <typename T> 74 struct result_type_deduction_helper<T const &> 75 { 76 typedef T const & type; 77 }; 78 } 79 80 namespace result_of 81 { 82 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR 83 // Bring in the result_of::actor<> 84 #include <boost/phoenix/core/detail/cpp03/actor_result_of.hpp> 85 #else 86 template <typename Expr, typename... A> 87 struct actor_impl 88 { 89 typedef 90 typename boost::phoenix::evaluator::impl< 91 Expr const& 92 , vector2< 93 typename vector_chooser<sizeof...(A) + 1>:: 94 template apply<const ::boost::phoenix::actor<Expr> *, A...>::type& 95 , default_actions 96 > const & 97 , proto::empty_env 98 >::result_type 99 type; 100 }; 101 102 template <typename Expr, typename... A> 103 struct actor : actor_impl<Expr, A...> {}; 104 105 template <typename Expr> 106 struct nullary_actor_result : actor_impl<Expr> {}; 107 #endif 108 109 template <typename Expr> 110 struct actor<Expr> 111 { 112 typedef 113 // avoid calling result_of::actor when this is false 114 typename mpl::eval_if_c< 115 result_of::is_nullary<Expr>::value 116 , nullary_actor_result<Expr> 117 , mpl::identity<detail::error_expecting_arguments> 118 >::type 119 type; 120 }; 121 } 122 123 //////////////////////////////////////////////////////////////////////////// 124 // 125 // actor 126 // 127 // The actor class. The main thing! In phoenix, everything is an actor 128 // This class is responsible for full function evaluation. Partial 129 // function evaluation involves creating a hierarchy of actor objects. 130 // 131 //////////////////////////////////////////////////////////////////////////// 132 template <typename Expr> 133 struct actor 134 { 135 typedef typename 136 mpl::eval_if_c< 137 mpl::or_< 138 is_custom_terminal<Expr> 139 , mpl::bool_<is_placeholder<Expr>::value> 140 >::value 141 , proto::terminal<Expr> 142 , mpl::identity<Expr> 143 >::type 144 expr_type; 145 146 BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<Expr>, phoenix_domain) 147 BOOST_PROTO_EXTENDS_SUBSCRIPT() 148 BOOST_PROTO_EXTENDS_ASSIGN_() 149 150 template <typename Sig> 151 struct result; 152 153 typename result_of::actor<proto_base_expr>::type operator ()boost::phoenix::actor154 operator()() 155 { 156 typedef vector1<const actor<Expr> *> env_type; 157 env_type env = {this}; 158 159 return phoenix::eval(*this, phoenix::context(env, default_actions())); 160 } 161 162 typename result_of::actor<proto_base_expr>::type operator ()boost::phoenix::actor163 operator()() const 164 { 165 typedef vector1<const actor<Expr> *> env_type; 166 env_type env = {this}; 167 168 return phoenix::eval(*this, phoenix::context(env, default_actions())); 169 } 170 171 template <typename Env> 172 typename evaluator::impl< 173 proto_base_expr const & 174 , typename result_of::context< 175 Env const & 176 , default_actions const & 177 >::type 178 , proto::empty_env 179 >::result_type evalboost::phoenix::actor180 eval(Env const & env) const 181 { 182 return phoenix::eval(*this, phoenix::context(env, default_actions())); 183 } 184 185 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR 186 // Bring in the rest 187 #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp> 188 #else 189 template <typename This, typename... A> 190 struct result<This(A...)> 191 : result_of::actor< 192 proto_base_expr 193 , typename mpl::if_<is_reference<A>, A, A const &>::type... 194 > 195 {}; 196 197 template <typename... A> 198 typename result<actor(A...)>::type operator ()boost::phoenix::actor199 operator()(A &&... a) 200 { 201 typedef 202 typename vector_chooser<sizeof...(A) + 1>::template apply< 203 const actor<Expr> * 204 , typename mpl::if_<is_reference<A>, A, A const &>::type... 205 >::type 206 env_type; 207 208 env_type env = {this, a...}; 209 return phoenix::eval(*this, phoenix::context(env, default_actions())); 210 } 211 212 template <typename... A> 213 typename result<actor(A...)>::type operator ()boost::phoenix::actor214 operator()(A &&... a) const 215 { 216 typedef 217 typename vector_chooser<sizeof...(A) + 1>::template apply< 218 const actor<Expr> * 219 , typename mpl::if_<is_reference<A>, A, A const &>::type... 220 >::type 221 env_type; 222 223 env_type env = {this, a...}; 224 return phoenix::eval(*this, phoenix::context(env, default_actions())); 225 } 226 #endif 227 228 BOOST_DELETED_FUNCTION(actor& operator=(actor const&)) 229 }; 230 }} 231 232 namespace boost 233 { 234 // specialize boost::result_of to return the proper result type 235 template <typename Expr> 236 struct result_of<phoenix::actor<Expr>()> 237 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> 238 {}; 239 240 template <typename Expr> 241 struct result_of<phoenix::actor<Expr> const()> 242 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> 243 {}; 244 } 245 246 247 #ifdef BOOST_MSVC 248 #pragma warning(pop) 249 #endif 250 251 #endif 252 253