| /*============================================================================= |
| Copyright (c) 2001-2007 Joel de Guzman |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ==============================================================================*/ |
| #ifndef PHOENIX_CORE_ACTOR_HPP |
| #define PHOENIX_CORE_ACTOR_HPP |
| |
| #include <boost/spirit/home/phoenix/core/limits.hpp> |
| |
| #if !defined(BOOST_RESULT_OF_NUM_ARGS) |
| # define BOOST_RESULT_OF_NUM_ARGS PHOENIX_ACTOR_LIMIT |
| #elif (BOOST_RESULT_OF_NUM_ARGS < PHOENIX_ACTOR_LIMIT) |
| # error "BOOST_RESULT_OF_NUM_ARGS < PHOENIX_ACTOR_LIMIT" |
| #endif |
| |
| #include <boost/spirit/home/phoenix/core/basic_environment.hpp> |
| #include <boost/mpl/min.hpp> |
| #include <boost/mpl/identity.hpp> |
| #include <boost/type_traits/add_const.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| #include <boost/utility/result_of.hpp> |
| |
| namespace boost { namespace phoenix |
| { |
| // phoenix::void_ is the same as fusion::void_ |
| typedef fusion::void_ void_; |
| |
| namespace detail |
| { |
| // Forward declarations. These will come in when we get to the |
| // operator module, yet, the actor's assignment operator and index |
| // operator are required to be members. |
| |
| template <typename T0, typename T1> |
| struct make_assign_composite; |
| |
| template <typename T0, typename T1> |
| struct make_index_composite; |
| |
| template <typename BaseT0, typename BaseT1> |
| struct comma_result; |
| |
| // error no arguments supplied |
| struct error_expecting_arguments |
| { |
| template <typename T> |
| error_expecting_arguments(T const&) {} |
| }; |
| } |
| |
| template <typename Eval, typename Env> |
| struct eval_result |
| { |
| typedef typename Eval::template result<Env>::type type; |
| }; |
| |
| template <typename Eval> |
| struct actor : Eval |
| { |
| typedef actor<Eval> self_type; |
| typedef Eval eval_type; |
| |
| template <class Sig> struct result {}; |
| |
| actor() |
| : Eval() {} |
| |
| actor(Eval const& base) |
| : Eval(base) {} |
| |
| template <typename T0> |
| explicit actor(T0 const& _0) |
| : Eval(_0) {} |
| |
| template <typename T0, typename T1> |
| actor(T0 const& _0, T1 const& _1) |
| : Eval(_0, _1) {} |
| |
| typedef typename |
| mpl::eval_if< |
| typename Eval::no_nullary // avoid calling eval_result when this is true |
| , mpl::identity<detail::error_expecting_arguments> |
| , eval_result<eval_type, basic_environment<> > |
| >::type |
| nullary_result; |
| |
| nullary_result |
| operator()() const |
| { |
| return eval_type::eval(basic_environment<>()); |
| } |
| |
| template <class F, class A0> |
| struct result<F(A0)> |
| : eval_result< |
| eval_type |
| , basic_environment< |
| typename remove_reference<A0>::type |
| > |
| > |
| {}; |
| |
| template <typename T0> |
| typename result<actor(T0&)>::type |
| operator()(T0& _0) const |
| { |
| return eval_type::eval(basic_environment<T0>(_0)); |
| } |
| |
| template <class F, class A0, class A1> |
| struct result<F(A0,A1)> |
| : eval_result< |
| eval_type |
| , basic_environment< |
| typename remove_reference<A0>::type |
| , typename remove_reference<A1>::type |
| > |
| > |
| {}; |
| |
| template <typename T0, typename T1> |
| typename result<actor(T0&,T1&)>::type |
| operator()(T0& _0, T1& _1) const |
| { |
| return eval_type::eval(basic_environment<T0, T1>(_0, _1)); |
| } |
| |
| template <typename T1> |
| typename detail::make_assign_composite<self_type, T1>::type |
| operator=(T1 const& a1) const; |
| |
| template <typename T1> |
| typename detail::make_index_composite<self_type, T1>::type |
| operator[](T1 const& a1) const; |
| |
| // Bring in the rest of the constructors and function call operators |
| #include <boost/spirit/home/phoenix/core/detail/actor.hpp> |
| |
| private: |
| // silence MSVC warning C4512: assignment operator could not be generated |
| actor& operator= (actor const&); |
| }; |
| |
| // Forward declaration: The intent to overload the comma must be |
| // stated early on to avoid the subtle problem that arises when |
| // the header file where the comma operator overload is defined, |
| // is not included by the client and the client attempts to use |
| // the comma anyway. |
| |
| namespace detail |
| { |
| template <typename BaseT0, typename BaseT1> |
| struct comma_result; |
| } |
| |
| template <typename BaseT0, typename BaseT1> |
| typename detail::comma_result<BaseT0, BaseT1>::type |
| operator,(actor<BaseT0> const& a0, actor<BaseT1> const& a1); |
| }} |
| |
| namespace boost |
| { |
| template <typename Eval> |
| struct result_of<phoenix::actor<Eval>()> |
| { |
| typedef typename phoenix::actor<Eval>::nullary_result type; |
| }; |
| |
| template <typename Eval> |
| struct result_of<phoenix::actor<Eval> const()> |
| : result_of<phoenix::actor<Eval>()> |
| {}; |
| } |
| |
| #endif |