]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 Core] | |
11 | ||
12 | Actors are composed to create more complex actors in a tree-like hierarchy. The | |
13 | primitives are atomic entities that are like the leaves in the tree. Phoenix is | |
14 | extensible. New primitives can be added anytime. Right out of the box, there are | |
15 | only a few primitives, these are all defined in the Core module. | |
16 | ||
17 | This section shall deal with these preset primitives. | |
18 | ||
19 | [section Values] | |
20 | ||
21 | ||
22 | #include <boost/phoenix/core/value.hpp> | |
23 | ||
24 | Whenever we see a constant in a partially applied function, an | |
25 | ||
26 | expression::value<T>::type | |
27 | ||
28 | (where T is the type of the constant) is automatically created for | |
29 | us. For instance: | |
30 | ||
31 | add(arg1, 6) | |
32 | ||
33 | Passing a second argument, `6`, an `expression::value<T>::type` is implicitly created | |
34 | behind the scenes. This is also equivalent to `add(arg1, val(6))`. | |
35 | ||
36 | val(v) | |
37 | ||
38 | generates an `expression::value<T>::type` where `T` is the type of `x`. In most | |
39 | cases, there's no need to explicitly use `val`, but, as we'll see later on, | |
40 | there are situations where this is unavoidable. | |
41 | ||
42 | [h2 Evaluating a Value] | |
43 | ||
44 | Like arguments, values are also actors. As such, values can be evaluated. | |
45 | Invoking a value gives the value's identity. Example: | |
46 | ||
47 | cout << val(3)() << val("Hello World")(); | |
48 | ||
49 | prints out "3 Hello World". | |
50 | ||
51 | [endsect] | |
52 | ||
53 | [section References] | |
54 | ||
55 | #include <boost/phoenix/core/reference.hpp> | |
56 | ||
57 | Values are immutable constants. Attempting to modify a value will result in a | |
58 | compile time error. When we want the function to modify the parameter, we use a | |
59 | reference instead. For instance, imagine a lazy function `add_assign`: | |
60 | ||
61 | void add_assign(T& x, T y) { x += y; } // pseudo code | |
62 | ||
63 | Here, we want the first function argument, x, to be mutable. Obviously, we | |
64 | cannot write: | |
65 | ||
66 | add_assign(1, 2) // error first argument is immutable | |
67 | ||
68 | In C++, we can pass in a reference to a variable as the first argument in our | |
69 | example above. Yet, by default, the library forces arguments passed to partially | |
70 | applied functions to be immutable values (see [link phoenix.modules.core.values | |
71 | Values]). To achieve our intent, we use: | |
72 | ||
73 | expression::reference<T>::type | |
74 | ||
75 | This is similar to `expression::value<T>::type` before but instead holds a reference to a | |
76 | variable. | |
77 | ||
78 | We normally don't instantiate `expression::reference<T>::type` objects directly. Instead we | |
79 | use: | |
80 | ||
81 | ref(v) | |
82 | ||
83 | For example (where `i` is an `int` variable): | |
84 | ||
85 | add_assign(ref(i), 2) | |
86 | ||
87 | [heading Evaluating a Reference] | |
88 | ||
89 | References are actors. Hence, references can be evaluated. Such invocation gives | |
90 | the reference's identity. Example: | |
91 | ||
92 | int i = 3; | |
93 | char const* s = "Hello World"; | |
94 | cout << ref(i)() << ref(s)(); | |
95 | ||
96 | prints out "3 Hello World" | |
97 | ||
98 | ||
99 | [heading Constant References] | |
100 | ||
101 | Another free function | |
102 | ||
103 | cref(cv) | |
104 | ||
105 | may also be used. `cref(cv)` creates an | |
106 | `expression::reference<T const>::type` object. This is similar to `expression::value<T>::type` but | |
107 | when the data to be passed as argument to a function is heavy and expensive to | |
108 | copy by value, the `cref(cv)` offers a lighter alternative. | |
109 | ||
110 | [endsect] | |
111 | ||
112 | [section Arguments] | |
113 | ||
114 | #include <boost/phoenix/core/argument.hpp> | |
115 | ||
116 | We use an instance of: | |
117 | ||
118 | expression::argument<N>::type | |
119 | ||
120 | to represent the Nth function argument. The argument placeholder acts as an | |
121 | imaginary data-bin where a function argument will be placed. | |
122 | ||
123 | [heading Predefined Arguments] | |
124 | ||
125 | There are a few predefined instances of `expression::argument<N>::type` named | |
126 | `arg1`..`argN`, and its __bll__ counterpart `_1`..`_N`. (where N is a predefined | |
127 | maximum). | |
128 | ||
129 | Here are some sample preset definitions of `arg1`..`argN` | |
130 | ||
131 | namespace placeholders | |
132 | { | |
133 | expression::argument<1>::type const arg1 = {}; | |
134 | expression::argument<2>::type const arg2 = {}; | |
135 | expression::argument<3>::type const arg3 = {}; | |
136 | } | |
137 | ||
138 | and its __bll__ `_1`..`_N` style counterparts: | |
139 | ||
140 | ||
141 | namespace placeholders | |
142 | { | |
143 | expression::argument<1>::type const _1 = {}; | |
144 | expression::argument<2>::type const _2 = {}; | |
145 | expression::argument<3>::type const _3 = {}; | |
146 | } | |
147 | ||
148 | [note You can set `BOOST_PHOENIX_ARG_LIMIT`, the predefined maximum | |
149 | placeholder index. By default, `BOOST_PHOENIX_ARG_LIMIT` is set to `BOOST_PHOENIX_LIMIT` | |
150 | (See [link phoenix.actor Actor]).] | |
151 | ||
152 | [heading User Defined Arguments] | |
153 | ||
154 | When appropriate, you can define your own `argument` names. For example: | |
155 | ||
156 | expression::argument<1>::type x; // note one based index | |
157 | ||
158 | `x` may now be used as a parameter to a lazy function: | |
159 | ||
160 | add(x, 6) | |
161 | ||
162 | which is equivalent to: | |
163 | ||
164 | add(arg1, 6) | |
165 | ||
166 | [/note | |
167 | When dealing with argument placeholders the question arises whether you can call | |
168 | member functions on an `argument` actor. | |
169 | ||
170 | This is possible by supplying a custom `actor` which has a member | |
171 | generator function. See [link phoenix.advanced_topics.extending_actors Extending Actors] | |
172 | for more details. | |
173 | ] | |
174 | ||
175 | [heading Evaluating an Argument] | |
176 | ||
177 | An argument, when evaluated, selects the Nth argument from the those passed | |
178 | in by the client. | |
179 | ||
180 | For example: | |
181 | ||
182 | char c = 'A'; | |
183 | int i = 123; | |
184 | const char* s = "Hello World"; | |
185 | ||
186 | cout << arg1(c) << endl; // Get the 1st argument: c | |
187 | cout << arg1(i, s) << endl; // Get the 1st argument: i | |
188 | cout << arg2(i, s) << endl; // Get the 2nd argument: s | |
189 | ||
190 | will print out: | |
191 | ||
192 | A | |
193 | 123 | |
194 | Hello World | |
195 | ||
196 | [heading Extra Arguments] | |
197 | ||
198 | In C and C++, a function can have extra arguments that are not at all used by | |
199 | the function body itself. These extra arguments are simply ignored. | |
200 | ||
201 | Phoenix also allows extra arguments to be passed. For example, recall our | |
202 | original `add` function: | |
203 | ||
204 | add(arg1, arg2) | |
205 | ||
206 | We know now that partially applying this function results to a function that | |
207 | expects 2 arguments. However, the library is a bit more lenient and allows the | |
208 | caller to supply more arguments than is actually required. Thus, `add` actually | |
209 | allows 2 /or more/ arguments. For instance, with: | |
210 | ||
211 | add(arg1, arg2)(x, y, z) | |
212 | ||
213 | the third argument `z` is ignored. Taking this further, in-between arguments are | |
214 | also ignored. Example: | |
215 | ||
216 | add(arg1, arg5)(a, b, c, d, e) | |
217 | ||
218 | Here, arguments b, c, and d are ignored. The function `add` takes in the first | |
219 | argument (`arg1`) and the fifth argument (`arg5`). | |
220 | ||
221 | [note There are a few reasons why enforcing strict arity is not | |
222 | desirable. A case in point is the callback function. Typical callback functions | |
223 | provide more information than is actually needed. Lambda functions are often | |
224 | used as callbacks.] | |
225 | ||
226 | [endsect] | |
227 | ||
228 | [section Nothing] | |
229 | ||
230 | #include <boost/phoenix/core/nothing.hpp> | |
231 | ||
232 | Finally, the `expression::null<mpl::void_>::type` does nothing; (a "bum", if you will :-) ). | |
233 | There's a sole `expression::null<mpl::void_>::type` instance named "nothing". This actor is | |
234 | actually useful in situations where we don't want to do anything. (See | |
235 | [link phoenix.modules.statement.for_statement for_ Statement] for example). | |
236 | ||
237 | [endsect] | |
238 | ||
239 | [endsect] |