/*============================================================================= Phoenix V1.0 Copyright (c) 2001-2002 Joel de Guzman Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. ==============================================================================*/ #ifndef PHOENIX_ACTOR_HPP #define PHOENIX_ACTOR_HPP /////////////////////////////////////////////////////////////////////////////// #include "boost/spirit/phoenix/tuples.hpp" /////////////////////////////////////////////////////////////////////////////// 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; } namespace impl { /////////////////////////////////////////////////////////////////////////// // // if_t selects type A or B depending on the condition C If C is of // type char[2], B is selected, otherwise A // // TODO: This should be part of a common meta-library // /////////////////////////////////////////////////////////////////////////// template struct if_t { typedef A type; }; template struct if_t { typedef B type; }; } /////////////////////////////////////////////////////////////////////////////// // // 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 ---------| // arg3 ---------|---> 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; }; ////////////////////////////////// template struct actor : public BaseT { actor(); actor(BaseT const& base); template actor(T const& arg) : BaseT(arg) {} 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; }; /////////////////////////////////////////////////////////////////////////// // // 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