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