/*============================================================================= | |
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 <boost/spirit/home/classic/phoenix/actor.hpp> | |
#include <boost/spirit/home/classic/phoenix/composite.hpp> | |
/////////////////////////////////////////////////////////////////////////////// | |
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<A...TN> (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 <typename Arg> | |
// struct result { typedef Arg type; }; | |
// | |
// template <typename Arg> | |
// 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_impl> 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_impl> 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 <typename OperationT> | |
struct function { | |
function() : op() {} | |
function(OperationT const& op_) : op(op_) {} | |
actor<composite<OperationT> > | |
operator()() const; | |
template <typename A> | |
typename impl::make_composite<OperationT, A>::type | |
operator()(A const& a) const; | |
template <typename A, typename B> | |
typename impl::make_composite<OperationT, A, B>::type | |
operator()(A const& a, B const& b) const; | |
template <typename A, typename B, typename C> | |
typename impl::make_composite<OperationT, A, B, C>::type | |
operator()(A const& a, B const& b, C const& c) const; | |
#if PHOENIX_LIMIT > 3 | |
template <typename A, typename B, typename C, typename D> | |
typename impl::make_composite<OperationT, A, B, C, D>::type | |
operator()(A const& a, B const& b, C const& c, D const& d) const; | |
template <typename A, typename B, typename C, typename D, typename E> | |
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 <typename OperationT> | |
inline actor<composite<OperationT> > | |
function<OperationT>::operator()() const | |
{ | |
return actor<composite<OperationT> >(op); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
template <typename A> | |
inline typename impl::make_composite<OperationT, A>::type | |
function<OperationT>::operator()(A const& a) const | |
{ | |
typedef typename impl::make_composite<OperationT, A>::composite_type ret_t; | |
return ret_t | |
( | |
op, | |
as_actor<A>::convert(a) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
template <typename A, typename B> | |
inline typename impl::make_composite<OperationT, A, B>::type | |
function<OperationT>::operator()(A const& a, B const& b) const | |
{ | |
typedef | |
typename impl::make_composite<OperationT, A, B>::composite_type | |
ret_t; | |
return ret_t( | |
op, | |
as_actor<A>::convert(a), | |
as_actor<B>::convert(b) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
template <typename A, typename B, typename C> | |
inline typename impl::make_composite<OperationT, A, B, C>::type | |
function<OperationT>::operator()(A const& a, B const& b, C const& c) const | |
{ | |
typedef | |
typename impl::make_composite<OperationT, A, B, C>::composite_type | |
ret_t; | |
return ret_t( | |
op, | |
as_actor<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c) | |
); | |
} | |
#if PHOENIX_LIMIT > 3 | |
////////////////////////////////// | |
template <typename OperationT> | |
template < | |
typename A, typename B, typename C, typename D | |
> | |
inline typename impl::make_composite< | |
OperationT, A, B, C, D | |
>::type | |
function<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
template < | |
typename A, typename B, typename C, typename D, typename E | |
> | |
inline typename impl::make_composite< | |
OperationT, A, B, C, D, E | |
>::type | |
function<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f) | |
); | |
} | |
#if PHOENIX_LIMIT > 6 | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i) | |
); | |
} | |
#if PHOENIX_LIMIT > 9 | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j), | |
as_actor<K>::convert(k) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j), | |
as_actor<K>::convert(k), | |
as_actor<L>::convert(l) | |
); | |
} | |
#if PHOENIX_LIMIT > 12 | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j), | |
as_actor<K>::convert(k), | |
as_actor<L>::convert(l), | |
as_actor<M>::convert(m) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j), | |
as_actor<K>::convert(k), | |
as_actor<L>::convert(l), | |
as_actor<M>::convert(m), | |
as_actor<N>::convert(n) | |
); | |
} | |
////////////////////////////////// | |
template <typename OperationT> | |
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<OperationT>::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<A>::convert(a), | |
as_actor<B>::convert(b), | |
as_actor<C>::convert(c), | |
as_actor<D>::convert(d), | |
as_actor<E>::convert(e), | |
as_actor<F>::convert(f), | |
as_actor<G>::convert(g), | |
as_actor<H>::convert(h), | |
as_actor<I>::convert(i), | |
as_actor<J>::convert(j), | |
as_actor<K>::convert(k), | |
as_actor<L>::convert(l), | |
as_actor<M>::convert(m), | |
as_actor<N>::convert(n), | |
as_actor<O>::convert(o) | |
); | |
} | |
#endif | |
#endif | |
#endif | |
#endif | |
/////////////////////////////////////////////////////////////////////////////// | |
} // namespace phoenix | |
#endif |