/*============================================================================= Phoenix V1.2.1 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_FUNCTIONS_HPP #define PHOENIX_FUNCTIONS_HPP /////////////////////////////////////////////////////////////////////////////// #include #include /////////////////////////////////////////////////////////////////////////////// namespace phoenix { /////////////////////////////////////////////////////////////////////////////// // // function class // // Lazy functions // // This class provides a mechanism for lazily evaluating functions. // Syntactically, a lazy function looks like an ordinary C/C++ // function. The function call looks the same. However, unlike // ordinary functions, the actual function execution is deferred. // (see actor.hpp, primitives.hpp and composite.hpp for an // overview). For example here are sample factorial function calls: // // factorial(4) // factorial(arg1) // factorial(arg1 * 6) // // These functions are automatically lazily bound unlike ordinary // function pointers or functor objects that need to be explicitly // bound through the bind function (see binders.hpp). // // A lazy function works in conjunction with a user defined functor // (as usual with a member operator()). Only special forms of // functor objects are allowed. This is required to enable true // polymorphism (STL style monomorphic functors and function // pointers can still be used through the bind facility in // binders.hpp). // // This special functor is expected to have a nested template class // result (where N is the number of arguments of its // member operator()). The nested template class result should have // a typedef 'type' that reflects the return type of its member // operator(). This is essentially a type computer that answers the // metaprogramming question "Given arguments of type A...TN, what // will be the operator()'s return type?". // // There is a special case for functors that accept no arguments. // Such nullary functors are only required to define a typedef // result_type that reflects the return type of its operator(). // // Here's an example of a simple functor that computes the // factorial of a number: // // struct factorial_impl { // // template // struct result { typedef Arg type; }; // // template // Arg operator()(Arg n) const // { return (n <= 0) ? 1 : n * this->operator()(n-1); } // }; // // As can be seen, the functor can be polymorphic. Its arguments // and return type are not fixed to a particular type. The example // above for example, can handle any type as long as it can carry // out the required operations (i.e. <=, * and -). // // We can now declare and instantiate a lazy 'factorial' function: // // function factorial; // // Invoking a lazy function 'factorial' does not immediately // execute the functor factorial_impl. Instead, a composite (see // composite.hpp) object is created and returned to the caller. // Example: // // factorial(arg1) // // does nothing more than return a composite. A second function // call will invoke the actual factorial function. Example: // // int i = 4; // cout << factorial(arg1)(i); // // will print out "24". // // Take note that in certain cases (e.g. for functors with state), // an instance may be passed on to the constructor. Example: // // function factorial(ftor); // // where ftor is an instance of factorial_impl (this is not // necessary in this case since factorial is a simple stateless // functor). Take care though when using functors with state // because the functors are taken in by value. It is best to keep // the data manipulated by a functor outside the functor itself and // keep a reference to this data inside the functor. Also, it is // best to keep functors as small as possible. // /////////////////////////////////////////////////////////////////////////////// template struct function { function() : op() {} function(OperationT const& op_) : op(op_) {} actor > operator()() const; template typename impl::make_composite::type operator()(A const& a) const; template typename impl::make_composite::type operator()(A const& a, B const& b) const; template typename impl::make_composite::type operator()(A const& a, B const& b, C const& c) const; #if PHOENIX_LIMIT > 3 template typename impl::make_composite::type operator()(A const& a, B const& b, C const& c, D const& d) const; template typename impl::make_composite< OperationT, A, B, C, D, E >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e ) const; template < typename A, typename B, typename C, typename D, typename E, typename F > typename impl::make_composite< OperationT, A, B, C, D, E, F >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f ) const; #if PHOENIX_LIMIT > 6 template < typename A, typename B, typename C, typename D, typename E, typename F, typename G > typename impl::make_composite< OperationT, A, B, C, D, E, F, G >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g ) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h ) const; template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& m, N const& 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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O >::type operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& m, N const& n, O const& o ) const; #endif #endif #endif #endif OperationT op; }; /////////////////////////////////////////////////////////////////////////////// // // function class implementation // /////////////////////////////////////////////////////////////////////////////// template inline actor > function::operator()() const { return actor >(op); } ////////////////////////////////// template template inline typename impl::make_composite::type function::operator()(A const& a) const { typedef typename impl::make_composite::composite_type ret_t; return ret_t ( op, as_actor::convert(a) ); } ////////////////////////////////// template template inline typename impl::make_composite::type function::operator()(A const& a, B const& b) const { typedef typename impl::make_composite::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b) ); } ////////////////////////////////// template template inline typename impl::make_composite::type function::operator()(A const& a, B const& b, C const& c) const { typedef typename impl::make_composite::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c) ); } #if PHOENIX_LIMIT > 3 ////////////////////////////////// template template < typename A, typename B, typename C, typename D > inline typename impl::make_composite< OperationT, A, B, C, D >::type function::operator()( A const& a, B const& b, C const& c, D const& d ) const { typedef typename impl::make_composite< OperationT, A, B, C, D >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E > inline typename impl::make_composite< OperationT, A, B, C, D, E >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F > inline typename impl::make_composite< OperationT, A, B, C, D, E, F >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f) ); } #if PHOENIX_LIMIT > 6 ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G > inline typename impl::make_composite< OperationT, A, B, C, D, E, F, G >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H > inline typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h) ); } ////////////////////////////////// template template < typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I > inline typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(j), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(j), as_actor::convert(k), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& m ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(j), as_actor::convert(k), as_actor::convert(l), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& m, N const& n ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(j), as_actor::convert(k), as_actor::convert(l), as_actor::convert(m), as_actor::convert(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 impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O >::type function::operator()( A const& a, B const& b, C const& c, D const& d, E const& e, F const& f, G const& g, H const& h, I const& i, J const& j, K const& k, L const& l, M const& m, N const& n, O const& o ) const { typedef typename impl::make_composite< OperationT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O >::composite_type ret_t; return ret_t( op, as_actor::convert(a), as_actor::convert(b), as_actor::convert(c), as_actor::convert(d), as_actor::convert(e), as_actor::convert(f), as_actor::convert(g), as_actor::convert(h), as_actor::convert(i), as_actor::convert(j), as_actor::convert(k), as_actor::convert(l), as_actor::convert(m), as_actor::convert(n), as_actor::convert(o) ); } #endif #endif #endif #endif /////////////////////////////////////////////////////////////////////////////// } // namespace phoenix #endif