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
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
13 #include <boost/phoenix/core/limits.hpp>
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>
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>
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
42 namespace boost { namespace phoenix
44 template <typename Expr>
49 struct error_expecting_arguments
52 error_expecting_arguments(T const&) {}
55 struct error_invalid_lambda_expr
58 error_invalid_lambda_expr(T const&) {}
62 struct result_type_deduction_helper
64 typedef T const & type;
68 struct result_type_deduction_helper<T &>
74 struct result_type_deduction_helper<T const &>
76 typedef T const & type;
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>
86 template <typename Expr, typename... A>
90 typename boost::phoenix::evaluator::impl<
93 typename vector_chooser<sizeof...(A) + 1>::
94 template apply<const ::boost::phoenix::actor<Expr> *, A...>::type&
102 template <typename Expr, typename... A>
103 struct actor : actor_impl<Expr, A...> {};
105 template <typename Expr>
106 struct nullary_actor_result : actor_impl<Expr> {};
109 template <typename Expr>
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>
123 ////////////////////////////////////////////////////////////////////////////
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.
131 ////////////////////////////////////////////////////////////////////////////
132 template <typename Expr>
138 is_custom_terminal<Expr>
139 , mpl::bool_<is_placeholder<Expr>::value>
141 , proto::terminal<Expr>
142 , mpl::identity<Expr>
146 BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<Expr>, phoenix_domain)
147 BOOST_PROTO_EXTENDS_SUBSCRIPT()
148 BOOST_PROTO_EXTENDS_ASSIGN_()
150 template <typename Sig>
153 typename result_of::actor<proto_base_expr>::type
156 typedef vector1<const actor<Expr> *> env_type;
157 env_type env = {this};
159 return phoenix::eval(*this, phoenix::context(env, default_actions()));
162 typename result_of::actor<proto_base_expr>::type
165 typedef vector1<const actor<Expr> *> env_type;
166 env_type env = {this};
168 return phoenix::eval(*this, phoenix::context(env, default_actions()));
171 template <typename Env>
172 typename evaluator::impl<
173 proto_base_expr const &
174 , typename result_of::context<
176 , default_actions const &
180 eval(Env const & env) const
182 return phoenix::eval(*this, phoenix::context(env, default_actions()));
185 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
187 #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp>
189 template <typename This, typename... A>
190 struct result<This(A...)>
193 , typename mpl::if_<is_reference<A>, A, A const &>::type...
197 template <typename... A>
198 typename result<actor(A...)>::type
199 operator()(A &&... a)
202 typename vector_chooser<sizeof...(A) + 1>::template apply<
204 , typename mpl::if_<is_reference<A>, A, A const &>::type...
208 env_type env = {this, a...};
209 return phoenix::eval(*this, phoenix::context(env, default_actions()));
212 template <typename... A>
213 typename result<actor(A...)>::type
214 operator()(A &&... a) const
217 typename vector_chooser<sizeof...(A) + 1>::template apply<
219 , typename mpl::if_<is_reference<A>, A, A const &>::type...
223 env_type env = {this, a...};
224 return phoenix::eval(*this, phoenix::context(env, default_actions()));
228 BOOST_DELETED_FUNCTION(actor& operator=(actor const&))
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>
240 template <typename Expr>
241 struct result_of<phoenix::actor<Expr> const()>
242 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>