• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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