1[/============================================================================== 2 Copyright (C) 2001-2010 Joel de Guzman 3 Copyright (C) 2001-2005 Dan Marsden 4 Copyright (C) 2001-2010 Thomas Heller 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8===============================================================================/] 9 10[section Function] 11 12The `function` class template provides a mechanism for implementing lazily 13evaluated functions. Syntactically, a lazy function looks like an ordinary C/C++ 14function. The function call looks familiar and feels the same as ordinary C++ 15functions. However, unlike ordinary functions, the actual function execution is 16deferred. 17 18 #include <boost/phoenix/function.hpp> 19 20Unlike ordinary function pointers or functor objects that need to be explicitly 21bound through the bind function (see [link phoenix.modules.bind Bind]), 22the argument types of these functions are automatically lazily bound. 23 24In order to create a lazy function, we need to implement a model of the 25__PFO__ concept. For a function that takes `N` arguments, a model of __PFO__ must 26provide: 27 28* An `operator()` that takes `N` arguments, and implements 29the function logic. This is also true for ordinary function pointers. 30* A nested metafunction `result<Signature>` or nested typedef `result_type`, following the __boost_result_of__ Protocol 31 32[/ 33* A nested metafunction `result<A1, ... AN>` that takes the types of the `N` arguments to 34the function and returns the result type of the function. (There is a special case for function 35objects that accept no arguments. Such nullary functors are only required to define a typedef 36`result_type` that reflects the return type of its `operator()`). 37] 38 39For example, the following type implements the FunctionEval concept, in order to provide a 40lazy factorial function: 41 42 struct factorial_impl 43 { 44 template <typename Sig> 45 struct result; 46 47 template <typename This, typename Arg> 48 struct result<This(Arg const &)> 49 { 50 typedef Arg type; 51 }; 52 53 template <typename Arg> 54 Arg operator()(Arg const & n) const 55 { 56 return (n <= 0) ? 1 : n * (*this)(n-1); 57 } 58 }; 59 60(See [@../../example/factorial.cpp factorial.cpp]) 61 62[/note The type of Arg is either a const-reference or non-const-reference 63(depending on whether your argument to the actor evaluation is a const-ref or 64non-const-ref).] 65 66Having implemented the `factorial_impl` type, we can declare and instantiate a lazy 67`factorial` function this way: 68 69 function<factorial_impl> factorial; 70 71Invoking a lazy function such as `factorial` does not immediately execute the function 72object `factorial_impl`. Instead, an [link phoenix.actor actor] object is 73created and returned to the caller. Example: 74 75 factorial(arg1) 76 77does nothing more than return an actor. A second function call will invoke 78the actual factorial function. Example: 79 80 std::cout << factorial(arg1)(4); 81 82will print out "24". 83 84Take note that in certain cases (e.g. for function objects with state), an 85instance of the model of __PFO__ may be passed on to the constructor. Example: 86 87 function<factorial_impl> factorial(ftor); 88 89where ftor is an instance of factorial_impl (this is not necessary in this case 90as `factorial_impl` does not require any state). 91 92[important Take care though when using function objects with state because they are 93often copied repeatedly, and state may change in one of the copies, rather than the 94original.] 95 96[section Adapting Functions] 97 98If you want to adapt already existing functions or function objects it will become 99a repetetive task. Therefor the following boilerplate macros are provided to help 100you adapt already exsiting functions, thus reducing the need to 101[link phoenix.modules.bind] functions. 102 103[section BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY] 104 105[heading Description] 106`BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY` is a macro that can be used to generate 107all the necessary boilerplate to make an arbitrary nullary function a lazy 108function. 109 110[note These macros generate no global objects. The resulting lazy functions are real functions 111 that create the lazy function expression object] 112 113[heading Synopsis] 114 115 BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY( 116 RETURN_TYPE 117 , LAZY_FUNCTION 118 , FUNCTION 119 ) 120 121[heading Semantics] 122 123The above macro generates all necessary code to have a nullary lazy function 124`LAZY_FUNCTION` which calls the nullary `FUNCTION` that has the return type 125`RETURN_TYPE` 126 127[heading Header] 128 129 #include <boost/phoenix/function/adapt_function.hpp> 130 131[heading Example] 132 133 namespace demo 134 { 135 int foo() 136 { 137 return 42; 138 } 139 } 140 141 BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int, foo, demo::foo) 142 143 int main() 144 { 145 using boost::phoenix::placeholders::_1; 146 147 assert((_1 + foo())(1) == 43); 148 } 149 150[endsect] 151 152[section BOOST_PHOENIX_ADAPT_FUNCTION] 153 154[heading Description] 155`BOOST_PHOENIX_ADAPT_FUNCTION` is a macro that can be used to generate 156all the necessary boilerplate to make an arbitrary function a lazy function. 157 158[heading Synopsis] 159 160 BOOST_PHOENIX_ADAPT_FUNCTION( 161 RETURN_TYPE 162 , LAZY_FUNCTION 163 , FUNCTION 164 , FUNCTION_ARITY 165 ) 166 167[heading Semantics] 168 169The above macro generates all necessary code to have a lazy function 170`LAZY_FUNCTION` which calls `FUNCTION` that has the return type 171`RETURN_TYPE` with `FUNCTION_ARITY` number of arguments. 172 173[heading Header] 174 175 #include <boost/phoenix/function/adapt_function.hpp> 176 177[heading Example] 178 179 namespace demo 180 { 181 int plus(int a, int b) 182 { 183 return a + b; 184 } 185 186 template <typename T> 187 T 188 plus(T a, T b, T c) 189 { 190 return a + b + c; 191 } 192 } 193 194 BOOST_PHOENIX_ADAPT_FUNCTION(int, plus, demo::plus, 2) 195 196 BOOST_PHOENIX_ADAPT_FUNCTION( 197 typename remove_reference<A0>::type 198 , plus 199 , demo::plus 200 , 3 201 ) 202 203 int main() 204 { 205 using boost::phoenix::arg_names::arg1; 206 using boost::phoenix::arg_names::arg2; 207 208 int a = 123; 209 int b = 256; 210 211 assert(plus(arg1, arg2)(a, b) == a+b); 212 assert(plus(arg1, arg2, 3)(a, b) == a+b+3); 213 } 214 215[endsect] 216 217[/ 218 219[section BOOST_PHOENIX_ADAPT_FUNCTION_VARARG] 220 221[heading Description] 222`BOOST_PHOENIX_ADAPT_FUNCTION_VARARG` is a macro that can be used to generate 223all the necessary boilerplate to make an arbitrary function a lazy 224function. 225 226[heading Synopsis] 227 228 BOOST_PHOENIX_ADAPT_FUNCTION_VARARG( 229 RETURN_TYPE 230 , LAZY_FUNCTION 231 , FUNCTION 232 ) 233 234[heading Semantics] 235 236[heading Header] 237 238 #include <boost/phoenix/function/adapt_function.hpp> 239 240[heading Example] 241 242[endsect] 243] 244 245[section BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY] 246 247[heading Description] 248`BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY` is a macro that can be used to generate 249all the necessary boilerplate to make an arbitrary nullary function object a 250lazy function. 251 252[heading Synopsis] 253 254 BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY( 255 LAZY_FUNCTION 256 , CALLABLE 257 ) 258 259[heading Semantics] 260 261The above macro generates all necessary code to create `LAZY_FUNCTION` which 262creates a lazy function object that represents a nullary call to `CALLABLE`. 263The return type is specified by `CALLABLE` conforming to the __boost_result_of__ 264protocol. 265 266[heading Header] 267 268 #include <boost/phoenix/function/adapt_callable.hpp> 269 270[heading Example] 271 272 namespace demo 273 { 274 struct foo 275 { 276 typedef int result_type; 277 278 result_type operator()() const 279 { 280 return 42; 281 } 282 } 283 } 284 285 BOOST_PHOENIX_ADAPT_CALLABLE_NULLARY(foo, demo::foo) 286 287 int main() 288 { 289 using boost::phoenix::placeholders::_1; 290 291 assert((_1 + foo())(1) == 43); 292 } 293 294[endsect] 295 296[section BOOST_PHOENIX_ADAPT_CALLABLE] 297 298[heading Description] 299`BOOST_PHOENIX_ADAPT_CALLABLE` is a macro that can be used to generate 300all the necessary boilerplate to make an arbitrary function object a lazy 301function. 302 303[heading Synopsis] 304 305 BOOST_PHOENIX_ADAPT_CALLABLE( 306 LAZY_FUNCTION 307 , FUNCTION_NAME 308 , FUNCTION_ARITY 309 ) 310 311[heading Semantics] 312 313The above macro generates all necessary code to create `LAZY_FUNCTION` which 314creates a lazy function object that represents a call to `CALLABLE` with `FUNCTION_ARITY` 315arguments. 316The return type is specified by `CALLABLE` conforming to the __boost_result_of__ 317protocol. 318 319[heading Header] 320 321 #include <boost/phoenix/function/adapt_callable.hpp> 322 323[heading Example] 324 325 namespace demo 326 { 327 struct plus 328 { 329 template <typename Sig> 330 struct result; 331 332 template <typename This, typename A0, typename A1> 333 struct result<This(A0, A1)> 334 : remove_reference<A0> 335 {}; 336 337 template <typename This, typename A0, typename A1, typename A2> 338 struct result<This(A0, A1, A2)> 339 : remove_reference<A0> 340 {}; 341 342 template <typename A0, typename A1> 343 A0 operator()(A0 const & a0, A1 const & a1) const 344 { 345 return a0 + a1; 346 } 347 348 template <typename A0, typename A1, typename A2> 349 A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const 350 { 351 return a0 + a1 + a2; 352 } 353 }; 354 } 355 356 BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 2) 357 358 BOOST_PHOENIX_ADAPT_CALLABLE(plus, demo::plus, 3) 359 360 int main() 361 { 362 using boost::phoenix::arg_names::arg1; 363 using boost::phoenix::arg_names::arg2; 364 365 int a = 123; 366 int b = 256; 367 368 assert(plus(arg1, arg2)(a, b) == a+b); 369 assert(plus(arg1, arg2, 3)(a, b) == a+b+3); 370 } 371 372[endsect] 373 374[/ 375[section BOOST_PHOENIX_ADAPT_CALLABLE_VARARG] 376 377[heading Description] 378`BOOST_PHOENIX_ADAPT_CALLABLE_VARARG` is a macro that can be used to generate 379all the necessary boilerplate to make an arbitrary function object a lazy 380function. 381 382[heading Synopsis] 383 384 BOOST_PHOENIX_ADAPT_CALLABLE_VARARG( 385 LAZY_FUNCTION_NAME 386 , FUNCTION_NAME 387 ) 388 389[heading Semantics] 390 391[heading Header] 392 393 #include <boost/phoenix/function/adapt_callable.hpp> 394 395[heading Example] 396 397[endsect] 398/] 399 400[endsect] 401 402[endsect] 403