actor.hpp 7.5 KB

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