]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. | |
3 | / Copyright (c) 2003-2008 Peter Dimov | |
4 | / | |
5 | / Distributed under the Boost Software License, Version 1.0. (See | |
6 | / accompanying file LICENSE_1_0.txt or copy at | |
7 | / http://www.boost.org/LICENSE_1_0.txt) | |
8 | /] | |
9 | ||
10 | [section:purpose Purpose] | |
11 | ||
12 | `boost::bind` is a generalization of the standard functions `std::bind1st` and | |
13 | `std::bind2nd`. It supports arbitrary function objects, functions, function | |
14 | pointers, and member function pointers, and is able to bind any argument to a | |
15 | specific value or route input arguments into arbitrary positions. `bind` does | |
16 | not place any requirements on the function object; in particular, it does not | |
17 | need the `result_type`, `first_argument_type` and `second_argument_type` | |
18 | standard typedefs. | |
19 | ||
20 | [section Using bind with functions and function pointers] | |
21 | ||
22 | Given these definitions: | |
23 | ||
24 | int f(int a, int b) | |
25 | { | |
26 | return a + b; | |
27 | } | |
28 | ||
29 | int g(int a, int b, int c) | |
30 | { | |
31 | return a + b + c; | |
32 | } | |
33 | ||
34 | `bind(f, 1, 2)` will produce a "nullary" function object that takes no | |
35 | arguments and returns `f(1, 2)`. Similarly, `bind(g, 1, 2, 3)()` is equivalent | |
36 | `to g(1, 2, 3)`. | |
37 | ||
38 | It is possible to selectively bind only some of the arguments. | |
39 | `bind(f, _1, 5)(x)` is equivalent to `f(x, 5)`; here `_1` is a /placeholder/ | |
40 | argument that means "substitute with the first input argument." | |
41 | ||
42 | For comparison, here is the same operation expressed with the standard library | |
43 | primitives: | |
44 | ||
45 | std::bind2nd(std::ptr_fun(f), 5)(x); | |
46 | ||
47 | `bind` covers the functionality of `std::bind1st` as well: | |
48 | ||
49 | std::bind1st(std::ptr_fun(f), 5)(x); // f(5, x) | |
50 | bind(f, 5, _1)(x); // f(5, x) | |
51 | ||
52 | `bind` can handle functions with more than two arguments, and its argument | |
53 | substitution mechanism is more general: | |
54 | ||
55 | bind(f, _2, _1)(x, y); // f(y, x) | |
56 | bind(g, _1, 9, _1)(x); // g(x, 9, x) | |
57 | bind(g, _3, _3, _3)(x, y, z); // g(z, z, z) | |
58 | bind(g, _1, _1, _1)(x, y, z); // g(x, x, x) | |
59 | ||
60 | Note that, in the last example, the function object produced by | |
61 | `bind(g, _1, _1, _1)` does not contain references to any arguments beyond the | |
62 | first, but it can still be used with more than one argument. Any extra | |
63 | arguments are silently ignored, just like the first and the second argument | |
64 | are ignored in the third example. | |
65 | ||
66 | The arguments that `bind` takes are copied and held internally by the returned | |
67 | function object. For example, in the following code: | |
68 | ||
69 | int i = 5; | |
70 | bind(f, i, _1); | |
71 | ||
72 | a copy of the value of `i` is stored into the function object. | |
73 | [@boost:/libs/core/doc/html/core/ref.html `boost::ref`] and | |
74 | [@boost:/libs/core/doc/html/core/ref.html `boost::cref`] can be used to make the function | |
75 | object store a reference to an object, rather than a copy: | |
76 | ||
77 | int i = 5; | |
78 | bind(f, ref(i), _1); | |
79 | bind(f, cref(i), _1); | |
80 | ||
81 | [endsect] | |
82 | ||
83 | [section:with_function_objects Using bind with function objects] | |
84 | ||
85 | `bind` is not limited to functions; it accepts arbitrary function objects. In | |
86 | the general case, the return type of the generated function object's | |
87 | `operator()` has to be specified explicitly (without a `typeof` operator the | |
88 | return type cannot be inferred): | |
89 | ||
90 | struct F | |
91 | { | |
92 | int operator()(int a, int b) { return a - b; } | |
93 | bool operator()(long a, long b) { return a == b; } | |
94 | }; | |
95 | ||
96 | F f; | |
97 | int x = 104; | |
98 | bind<int>(f, _1, _1)(x); // f(x, x), i.e. zero | |
99 | ||
100 | Some compilers have trouble with the `bind<R>(f, ...)` syntax. For portability | |
101 | reasons, an alternative way to express the above is supported: | |
102 | ||
103 | boost::bind(boost::type<int>(), f, _1, _1)(x); | |
104 | ||
105 | Note, however, that the alternative syntax is provided only as a workaround. | |
106 | It is not part of the interface. | |
107 | ||
108 | When the function object exposes a nested type named `result_type`, the explicit | |
109 | return type can be omitted: | |
110 | ||
111 | int x = 8; | |
112 | bind(std::less<int>(), _1, 9)(x); // x < 9 | |
113 | ||
114 | /[Note:/ the ability to omit the return type is not available on all compilers./]/ | |
115 | ||
116 | By default, `bind` makes a copy of the provided function object. `boost::ref` | |
117 | and `boost::cref` can be used to make it store a reference to the function | |
118 | object, rather than a copy. This can be useful when the function object is | |
119 | non-copyable, expensive to copy, or contains state; of course, in this case | |
120 | the programmer is expected to ensure that the function object is not destroyed | |
121 | while it's still being used. | |
122 | ||
123 | struct F2 | |
124 | { | |
125 | int s; | |
126 | ||
127 | typedef void result_type; | |
128 | void operator()(int x) { s += x; } | |
129 | }; | |
130 | ||
131 | F2 f2 = { 0 }; | |
132 | int a[] = { 1, 2, 3 }; | |
133 | ||
134 | std::for_each(a, a+3, bind(ref(f2), _1)); | |
135 | ||
136 | assert(f2.s == 6); | |
137 | ||
138 | [endsect] | |
139 | ||
140 | [section Using bind with pointers to members] | |
141 | ||
142 | Pointers to member functions and pointers to data members are not function | |
143 | objects, because they do not support `operator()`. For convenience, `bind` | |
144 | accepts member pointers as its first argument, and the behavior is as if | |
145 | [@boost:/libs/bind/mem_fn.html `boost::mem_fn`] has been used to convert the | |
146 | member pointer into a function object. In other words, the expression | |
147 | ||
148 | bind(&X::f, args) | |
149 | ||
150 | is equivalent to | |
151 | ||
152 | bind<R>(``[@boost:/libs/bind/mem_fn.html `mem_fn`]``(&X::f), args) | |
153 | ||
154 | where `R` is the return type of `X::f` (for member functions) or the type of | |
155 | the member (for data members.) | |
156 | ||
157 | /[Note:/ `mem_fn` creates function objects that are able to accept a pointer, | |
158 | a reference, or a smart pointer to an object as its first argument; for | |
159 | additional information, see the `mem_fn` | |
160 | [@boost:/libs/bind/mem_fn.html documentation]./]/ | |
161 | ||
162 | Example: | |
163 | ||
164 | struct X | |
165 | { | |
166 | bool f(int a); | |
167 | }; | |
168 | ||
169 | X x; | |
170 | shared_ptr<X> p(new X); | |
171 | int i = 5; | |
172 | ||
173 | bind(&X::f, ref(x), _1)(i); // x.f(i) | |
174 | bind(&X::f, &x, _1)(i); // (&x)->f(i) | |
175 | bind(&X::f, x, _1)(i); // (internal copy of x).f(i) | |
176 | bind(&X::f, p, _1)(i); // (internal copy of p)->f(i) | |
177 | ||
178 | The last two examples are interesting in that they produce "self-contained" | |
179 | function objects. `bind(&X::f, x, _1)` stores a copy of `x`. | |
180 | `bind(&X::f, p, _1)` stores a copy of `p`, and since `p` is a | |
181 | [@boost:/libs/smart_ptr/shared_ptr.htm `boost::shared_ptr`], the function | |
182 | object retains a reference to its instance of `X` and will remain valid even | |
183 | when `p` goes out of scope or is `reset()`. | |
184 | ||
185 | [endsect] | |
186 | ||
187 | [section Using nested binds for function composition] | |
188 | ||
189 | Some of the arguments passed to `bind` may be nested /bind expressions/ | |
190 | themselves: | |
191 | ||
192 | bind(f, bind(g, _1))(x); // f(g(x)) | |
193 | ||
194 | The inner /bind expressions/ are evaluated, in unspecified order, before the | |
195 | outer `bind` when the function object is called; the results of the evaluation | |
196 | are then substituted in their place when the outer `bind` is evaluated. In the | |
197 | example above, when the function object is called with the argument list `(x)`, | |
198 | `bind(g, _1)(x)` is evaluated first, yielding `g(x)`, and then | |
199 | `bind(f, g(x))(x)` is evaluated, yielding the final result `f(g(x))`. | |
200 | ||
201 | This feature of `bind` can be used to perform function composition. See | |
202 | [@../../bind_as_compose.cpp bind_as_compose.cpp] for an example that | |
203 | demonstrates how to use `bind` to achieve similar functionality to | |
204 | [@http://www.boost.org/doc/libs/1_31_0/libs/compose/index.htm Boost.Compose]. | |
205 | ||
206 | Note that the first argument - the bound function object - is not evaluated, | |
207 | even when it's a function object that is produced by `bind` or a /placeholder/ | |
208 | argument, so the example below does not work as expected: | |
209 | ||
210 | typedef void (*pf)(int); | |
211 | ||
212 | std::vector<pf> v; | |
213 | std::for_each(v.begin(), v.end(), bind(_1, 5)); | |
214 | ||
215 | The desired effect can be achieved via a helper function object `apply` that | |
216 | applies its first argument, as a function object, to the rest of its argument | |
217 | list. For convenience, an implementation of `apply` is provided in the | |
218 | [@../../../../boost/bind/apply.hpp apply.hpp] header file. Here is how the | |
219 | modified version of the previous example looks like: | |
220 | ||
221 | typedef void (*pf)(int); | |
222 | ||
223 | std::vector<pf> v; | |
224 | std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5)); | |
225 | ||
226 | Although the first argument is, by default, not evaluated, all other arguments | |
227 | are. Sometimes it is necessary not to evaluate arguments subsequent to the | |
228 | first, even when they are nested /bind subexpressions/. This can be achieved | |
229 | with the help of another function object, `protect`, that masks the type so | |
230 | that `bind` does not recognize and evaluate it. When called, protect simply | |
231 | forwards the argument list to the other function object unmodified. | |
232 | ||
233 | The header [@../../../../boost/bind/protect.hpp protect.hpp] contains an | |
234 | implementation of `protect`. To `protect` a bind function object from | |
235 | evaluation, use `protect(bind(f, ...))`. | |
236 | ||
237 | [endsect] | |
238 | ||
239 | [section Overloaded operators (new in Boost 1.33)] | |
240 | ||
241 | For convenience, the function objects produced by `bind` overload the logical | |
242 | not operator `!` and the relational and logical operators `==, !=, <, <=, >, | |
243 | >=, &&, ||`. | |
244 | ||
245 | `!bind(f, ...)` is equivalent to `bind(logical_not(), bind(f, ...))`, where | |
246 | `logical_not` is a function object that takes one argument `x` and returns | |
247 | `!x`. | |
248 | ||
249 | `bind(f, ...) op x`, where _op_ is a relational or logical operator, is | |
250 | equivalent to `bind(relation(), bind(f, ...), x)`, where `relation` is a | |
251 | function object that takes two arguments `a` and `b` and returns `a op b`. | |
252 | ||
253 | What this means in practice is that you can conveniently negate the result of | |
254 | `bind`: | |
255 | ||
256 | std::remove_if(first, last, !bind(&X::visible, _1)); // remove invisible objects | |
257 | ||
258 | and compare the result of `bind` against a value: | |
259 | ||
260 | std::find_if(first, last, bind(&X::name, _1) == "Peter"); | |
261 | std::find_if(first, last, bind(&X::name, _1) == "Peter" || bind(&X::name, _1) == "Paul"); | |
262 | ||
263 | against a /placeholder/: | |
264 | ||
265 | bind(&X::name, _1) == _2 | |
266 | ||
267 | or against another /bind expression/: | |
268 | ||
269 | std::sort(first, last, bind(&X::name, _1) < bind(&X::name, _2)); // sort by name | |
270 | ||
271 | [endsect] | |
272 | ||
273 | [endsect] |