/*============================================================================= Phoenix v1.2 Copyright (c) 2001-2002 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_ACTOR_HPP #define PHOENIX_ACTOR_HPP /////////////////////////////////////////////////////////////////////////////// #include /////////////////////////////////////////////////////////////////////////////// namespace phoenix { // These are forward declared here because we cannot include impl.hpp // or operators.hpp yet but the actor's assignment operator and index // operator are required to be members. ////////////////////////////////// struct assign_op; struct index_op; ////////////////////////////////// namespace impl { template struct make_binary1; } /////////////////////////////////////////////////////////////////////////////// // // unpack_tuple class // // This class is used to unpack a supplied tuple such, that the members of // this tuple will be handled as if they would be supplied separately. // /////////////////////////////////////////////////////////////////////////////// template struct unpack_tuple : public TupleT { typedef TupleT tuple_t; unpack_tuple() {} unpack_tuple(tuple_t const &tuple_) : TupleT(tuple_) {} }; /////////////////////////////////////////////////////////////////////////////// // // actor class // // This class is a protocol class for all actors. This class is // essentially an interface contract. The actor class does not // really know how how to act on anything but instead relies on the // template parameter BaseT (from which the actor will derive from) // to do the actual action. // // An actor is a functor that is capable of accepting arguments up // to a predefined maximum. It is up to the base class to do the // actual processing or possibly to limit the arity (no. of // arguments) passed in. Upon invocation of the functor through a // supplied operator(), the actor funnels the arguments passed in // by the client into a tuple and calls the base eval member // function. // // Schematically: // // arg0 ---------| // arg1 ---------| // arg2 ---------|---> tupled_args ---> base.eval // ... | // argN ---------| // // actor::operator()(arg0, arg1... argN) // ---> BaseT::eval(tupled_args); // // Actor base classes from which this class inherits from are // expected to have a corresponding member function eval compatible // with the conceptual Interface: // // template // actor_return_type // eval(TupleT const& args) const; // // where args are the actual arguments passed in by the client // funneled into a tuple (see tuple.hpp for details). // // The actor_return_type can be anything. Base classes are free to // return any type, even argument dependent types (types that are // deduced from the types of the arguments). After evaluating the // parameters and doing some computations or actions, the eval // member function concludes by returning something back to the // client. To do this, the forwarding function (the actor's // operator()) needs to know the return type of the eval member // function that it is calling. For this purpose, actor base // classes are required to provide a nested template class: // // template // struct result; // // This auxiliary class provides the result type information // returned by the eval member function of a base actor class. The // nested template class result should have a typedef 'type' that // reflects the return type of its member function eval. It is // basically a type computer that answers the question "given // arguments packed into a TupleT type, what will be the result // type of the eval member function of ActorT?". The template class // actor_result queries this to extract the return type of an // actor. Example: // // typedef typename actor_result::type // actor_return_type; // // where actor_return_type is the actual type returned by ActorT's // eval member function given some arguments in a TupleT. // /////////////////////////////////////////////////////////////////////////////// template struct actor_result { typedef typename ActorT::template result::type type; typedef typename remove_reference::type plain_type; }; ////////////////////////////////// #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(push) #pragma warning(disable:4512) //assignment operator could not be generated #endif template struct actor : public BaseT { actor(); actor(BaseT const& base); typename actor_result >::type operator()() const; template typename actor_result >::type operator()(A& a) const; template typename actor_result >::type operator()(A& a, B& b) const; template typename actor_result >::type operator()(A& a, B& b, C& c) const; #if PHOENIX_LIMIT > 3 template typename actor_result >::type operator()(A& a, B& b, C& c, D& d) const; template typename actor_result >::type operator()(A& a, B& b, C& c, D& d, E& e) const; template < typename A, typename B, typename C, typename D, typename E, typename F> typename actor_result >::type operator()(A& a, B& b, C& c, D& d, E& e, F& f) const; #if PHOENIX_LIMIT > 6 template < typename A, typename B, typename C, typename D, typename E, typename F, typename G> typename actor_result >::type operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> typename actor_result >::type operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> typename actor_result >::type operator()(A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i) const; #if PHOENIX_LIMIT > 9 template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, K& k) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, K& k, L& l) const; #if PHOENIX_LIMIT > 12 template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, K& k, L& l, M& m) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, K& k, L& l, M& m, N& n) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O> typename actor_result >::type operator()( A& a, B& b, C& c, D& d, E& e, F& f, G& g, H& h, I& i, J& j, K& k, L& l, M& m, N& n, O& o) const; #endif #endif #endif #endif template typename actor_result >::type operator()(unpack_tuple const &t) const; template typename impl::make_binary1::type operator=(B const& b) const; template typename impl::make_binary1::type operator[](B const& b) const; }; #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(pop) #endif /////////////////////////////////////////////////////////////////////////// // // as_actor // // as_actor is a meta-program that converts an arbitrary type into // an actor. All participants in the framework must be first-class // actors. This meta-program is used all throughout the framework // whenever an unknown type needs to be converted to an actor. // as_actor specializations are expected to have a typedef 'type'. // This is the destination actor type. A static member function // 'convert' converts an object to this target type. // // The meta-program does no conversion if the object to be // converted is already an actor. // /////////////////////////////////////////////////////////////////////////// template struct as_actor; ////////////////////////////////// template struct as_actor > { typedef actor type; static type convert(actor const& x) { return x; } }; ////////////////////////////////// template <> struct as_actor { typedef nil_t type; static nil_t convert(nil_t /*x*/) { return nil_t(); } }; ////////////////////////////////// template <> struct as_actor { typedef void type; // ERROR!!! }; /////////////////////////////////////////////////////////////////////////////// // // actor class implementation // /////////////////////////////////////////////////////////////////////////////// template actor::actor() : BaseT() {} ////////////////////////////////// template actor::actor(BaseT const& base) : BaseT(base) {} ////////////////////////////////// template inline typename actor_result >::type actor::operator()() const { return BaseT::eval(tuple<>()); } ////////////////////////////////// template template inline typename actor_result >::type actor::operator()(A& a_) const { return BaseT::eval(tuple(a_)); } ////////////////////////////////// template template inline typename actor_result >::type actor::operator()(A& a_, B& b_) const { return BaseT::eval(tuple(a_, b_)); } ////////////////////////////////// template template inline typename actor_result >::type actor::operator()(A& a_, B& b_, C& c_) const { return BaseT::eval(tuple(a_, b_, c_)); } #if PHOENIX_LIMIT > 3 ////////////////////////////////// template template inline typename actor_result >::type actor::operator()(A& a_, B& b_, C& c_, D& d_) const { return BaseT::eval(tuple(a_, b_, c_, d_)); } ////////////////////////////////// template template inline typename actor_result >::type actor::operator()(A& a_, B& b_, C& c_, D& d_, E& e_) const { return BaseT::eval(tuple(a_, b_, c_, d_, e_)); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_) ); } #if PHOENIX_LIMIT > 6 ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_) ); } #if PHOENIX_LIMIT > 9 ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_, K& k_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_, K& k_, L& l_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_) ); } #if PHOENIX_LIMIT > 12 ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_, K& k_, L& l_, M& m_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_, m_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_, K& k_, L& l_, M& m_, N& n_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_, m_, n_) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L, typename M, typename N, typename O> inline typename actor_result >::type actor::operator()( A& a_, B& b_, C& c_, D& d_, E& e_, F& f_, G& g_, H& h_, I& i_, J& j_, K& k_, L& l_, M& m_, N& n_, O& o_ ) const { return BaseT::eval( tuple (a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_, m_, n_, o_) ); } #endif #endif #endif #endif ////////////////////////////////// template template typename actor_result >::type actor::operator()(unpack_tuple const &t) const { return BaseT::eval(t); } /////////////////////////////////////////////////////////////////////////////// } // namespace phoenix #endif