[/============================================================================== Copyright (C) 2001-2010 Joel de Guzman Copyright (C) 2001-2005 Dan Marsden Copyright (C) 2001-2010 Thomas Heller 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) ===============================================================================/] [section Function] The `function` class template provides a mechanism for implementing lazily evaluated functions. Syntactically, a lazy function looks like an ordinary C/C++ function. The function call looks familiar and feels the same as ordinary C++ functions. However, unlike ordinary functions, the actual function execution is deferred. #include Unlike ordinary function pointers or functor objects that need to be explicitly bound through the bind function (see [link phoenix.modules.bind Bind]), the argument types of these functions are automatically lazily bound. In order to create a lazy function, we need to implement a model of the __PFO__ concept. For a function that takes `N` arguments, a model of __PFO__ must provide: * An `operator()` that takes `N` arguments, and implements the function logic. This is also true for ordinary function pointers. * A nested metafunction `result` or nested typedef `result_type`, following the __boost_result_of__ Protocol [/ * A nested metafunction `result` that takes the types of the `N` arguments to the function and returns the result type of the function. (There is a special case for function objects that accept no arguments. Such nullary functors are only required to define a typedef `result_type` that reflects the return type of its `operator()`). ] For example, the following type implements the FunctionEval concept, in order to provide a lazy factorial function: struct factorial_impl { template struct result; template struct result { typedef Arg type; }; template Arg operator()(Arg const & n) const { return (n <= 0) ? 1 : n * (*this)(n-1); } }; (See [@../../example/factorial.cpp factorial.cpp]) [/note The type of Arg is either a const-reference or non-const-reference (depending on whether your argument to the actor evaluation is a const-ref or non-const-ref).] Having implemented the `factorial_impl` type, we can declare and instantiate a lazy `factorial` function this way: function factorial; Invoking a lazy function such as `factorial` does not immediately execute the function object `factorial_impl`. Instead, an [link phoenix.actor actor] object is created and returned to the caller. Example: factorial(arg1) does nothing more than return an actor. A second function call will invoke the actual factorial function. Example: std::cout << factorial(arg1)(4); will print out "24". Take note that in certain cases (e.g. for function objects with state), an instance of the model of __PFO__ 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 as `factorial_impl` does not require any state). [important Take care though when using function objects with state because they are often copied repeatedly, and state may change in one of the copies, rather than the original.] [section Adapting Functions] If you want to adapt already existing functions or function objects it will become a repetetive task. Therefor the following boilerplate macros are provided to help you adapt already exsiting functions, thus reducing the need to [link phoenix.modules.bind] functions. [section BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY] [heading Description] `BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary nullary function a lazy function. [note These macros generate no global objects. The resulting lazy functions are real functions that create the lazy function expression object] [heading Synopsis] BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY( RETURN_TYPE , LAZY_FUNCTION , FUNCTION ) [heading Semantics] The above macro generates all necessary code to have a nullary lazy function `LAZY_FUNCTION` which calls the nullary `FUNCTION` that has the return type `RETURN_TYPE` [heading Header] #include [heading Example] namespace demo { int foo() { return 42; } } BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int, foo, demo::foo) int main() { using boost::phoenix::placeholders::_1; assert((_1 + foo())(1) == 43); } [endsect] [section BOOST_PHOENIX_ADAPT_FUNCTION] [heading Description] `BOOST_PHOENIX_ADAPT_FUNCTION` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary function a lazy function. [heading Synopsis] BOOST_PHOENIX_ADAPT_FUNCTION( RETURN_TYPE , LAZY_FUNCTION , FUNCTION , FUNCTION_ARITY ) [heading Semantics] The above macro generates all necessary code to have a lazy function `LAZY_FUNCTION` which calls `FUNCTION` that has the return type `RETURN_TYPE` with `FUNCTION_ARITY` number of arguments. [heading Header] #include [heading Example] namespace demo { int plus(int a, int b) { return a + b; } template T plus(T a, T b, T c) { return a + b + c; } } BOOST_PHOENIX_ADAPT_FUNCTION(int, plus, demo::plus, 2) BOOST_PHOENIX_ADAPT_FUNCTION( typename remove_reference::type , plus , demo::plus , 3 ) int main() { using boost::phoenix::arg_names::arg1; using boost::phoenix::arg_names::arg2; int a = 123; int b = 256; assert(plus(arg1, arg2)(a, b) == a+b); assert(plus(arg1, arg2, 3)(a, b) == a+b+3); } [endsect] [/ [section BOOST_PHOENIX_ADAPT_FUNCTION_VARARG] [heading Description] `BOOST_PHOENIX_ADAPT_FUNCTION_VARARG` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary function a lazy function. [heading Synopsis] BOOST_PHOENIX_ADAPT_FUNCTION_VARARG( RETURN_TYPE , LAZY_FUNCTION , FUNCTION ) [heading Semantics] [heading Header] #include [heading Example] [endsect] ] [section BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY] [heading Description] `BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary nullary function object a lazy function. [heading Synopsis] BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY( LAZY_FUNCTION , CALLABLE ) [heading Semantics] The above macro generates all necessary code to create `LAZY_FUNCTION` which creates a lazy function object that represents a nullary call to `CALLABLE`. The return type is specified by `CALLABLE` conforming to the __boost_result_of__ protocol. [heading Header] #include [heading Example] namespace demo { struct foo { typedef int result_type; result_type operator()() const { return 42; } } } BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(foo, demo::foo) int main() { using boost::phoenix::placeholders::_1; assert((_1 + foo())(1) == 43); } [endsect] [section BOOST_PHOENIX_ADAPT_CALLABLE] [heading Description] `BOOST_PHOENIX_ADAPT_CALLABLE` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary function object a lazy function. [heading Synopsis] BOOST_PHOENIX_ADAPT_CALLABLE( LAZY_FUNCTION , FUNCTION_NAME , FUNCTION_ARITY ) [heading Semantics] The above macro generates all necessary code to create `LAZY_FUNCTION` which creates a lazy function object that represents a call to `CALLABLE` with `FUNCTION_ARITY` arguments. The return type is specified by `CALLABLE` conforming to the __boost_result_of__ protocol. [heading Header] #include [heading Example] namespace demo { struct plus { template struct result; template struct result : remove_reference {}; template struct result : remove_reference {}; template A0 operator()(A0 const & a0, A1 const & a1) const { return a0 + a1; } template A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const { return a0 + a1 + a2; } }; } BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 2) BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 3) int main() { using boost::phoenix::arg_names::arg1; using boost::phoenix::arg_names::arg2; int a = 123; int b = 256; assert(plus(arg1, arg2)(a, b) == a+b); assert(plus(arg1, arg2, 3)(a, b) == a+b+3); } [endsect] [/ [section BOOST_PHOENIX_ADAPT_CALLABLE_VARARG] [heading Description] `BOOST_PHOENIX_ADAPT_CALLABLE_VARARG` is a macro that can be used to generate all the necessary boilerplate to make an arbitrary function object a lazy function. [heading Synopsis] BOOST_PHOENIX_ADAPT_CALLABLE_VARARG( LAZY_FUNCTION_NAME , FUNCTION_NAME ) [heading Semantics] [heading Header] #include [heading Example] [endsect] /] [endsect] [endsect]