]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/bind/doc/bind/purpose.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / bind / doc / bind / purpose.qbk
CommitLineData
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
14pointers, and member function pointers, and is able to bind any argument to a
15specific value or route input arguments into arbitrary positions. `bind` does
16not place any requirements on the function object; in particular, it does not
17need the `result_type`, `first_argument_type` and `second_argument_type`
18standard typedefs.
19
20[section Using bind with functions and function pointers]
21
22Given 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
35arguments and returns `f(1, 2)`. Similarly, `bind(g, 1, 2, 3)()` is equivalent
36 `to g(1, 2, 3)`.
37
38It 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/
40argument that means "substitute with the first input argument."
41
42For comparison, here is the same operation expressed with the standard library
43primitives:
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
53substitution 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
60Note 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
62first, but it can still be used with more than one argument. Any extra
63arguments are silently ignored, just like the first and the second argument
64are ignored in the third example.
65
66The arguments that `bind` takes are copied and held internally by the returned
67function object. For example, in the following code:
68
69 int i = 5;
70 bind(f, i, _1);
71
72a 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
75object 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
86the general case, the return type of the generated function object's
87`operator()` has to be specified explicitly (without a `typeof` operator the
88return 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
100Some compilers have trouble with the `bind<R>(f, ...)` syntax. For portability
101reasons, an alternative way to express the above is supported:
102
103 boost::bind(boost::type<int>(), f, _1, _1)(x);
104
105Note, however, that the alternative syntax is provided only as a workaround.
106It is not part of the interface.
107
108When the function object exposes a nested type named `result_type`, the explicit
109return 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
116By default, `bind` makes a copy of the provided function object. `boost::ref`
117and `boost::cref` can be used to make it store a reference to the function
118object, rather than a copy. This can be useful when the function object is
119non-copyable, expensive to copy, or contains state; of course, in this case
120the programmer is expected to ensure that the function object is not destroyed
121while 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
142Pointers to member functions and pointers to data members are not function
143objects, because they do not support `operator()`. For convenience, `bind`
144accepts 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
146member pointer into a function object. In other words, the expression
147
148 bind(&X::f, args)
149
150is equivalent to
151
152 bind<R>(``[@boost:/libs/bind/mem_fn.html `mem_fn`]``(&X::f), args)
153
154where `R` is the return type of `X::f` (for member functions) or the type of
155the member (for data members.)
156
157/[Note:/ `mem_fn` creates function objects that are able to accept a pointer,
158a reference, or a smart pointer to an object as its first argument; for
159additional information, see the `mem_fn`
160[@boost:/libs/bind/mem_fn.html documentation]./]/
161
162Example:
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
178The last two examples are interesting in that they produce "self-contained"
179function 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
182object retains a reference to its instance of `X` and will remain valid even
183when `p` goes out of scope or is `reset()`.
184
185[endsect]
186
187[section Using nested binds for function composition]
188
189Some of the arguments passed to `bind` may be nested /bind expressions/
190themselves:
191
192 bind(f, bind(g, _1))(x); // f(g(x))
193
194The inner /bind expressions/ are evaluated, in unspecified order, before the
195outer `bind` when the function object is called; the results of the evaluation
196are then substituted in their place when the outer `bind` is evaluated. In the
197example 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
201This feature of `bind` can be used to perform function composition. See
202[@../../bind_as_compose.cpp bind_as_compose.cpp] for an example that
203demonstrates 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
206Note that the first argument - the bound function object - is not evaluated,
207even when it's a function object that is produced by `bind` or a /placeholder/
208argument, 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
215The desired effect can be achieved via a helper function object `apply` that
216applies its first argument, as a function object, to the rest of its argument
217list. For convenience, an implementation of `apply` is provided in the
218[@../../../../boost/bind/apply.hpp apply.hpp] header file. Here is how the
219modified 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
226Although the first argument is, by default, not evaluated, all other arguments
227are. Sometimes it is necessary not to evaluate arguments subsequent to the
228first, even when they are nested /bind subexpressions/. This can be achieved
229with the help of another function object, `protect`, that masks the type so
230that `bind` does not recognize and evaluate it. When called, protect simply
231forwards the argument list to the other function object unmodified.
232
233The header [@../../../../boost/bind/protect.hpp protect.hpp] contains an
234implementation of `protect`. To `protect` a bind function object from
235evaluation, use `protect(bind(f, ...))`.
236
237[endsect]
238
239[section Overloaded operators (new in Boost 1.33)]
240
241For convenience, the function objects produced by `bind` overload the logical
242not 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
250equivalent to `bind(relation(), bind(f, ...), x)`, where `relation` is a
251function object that takes two arguments `a` and `b` and returns `a op b`.
252
253What 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
258and 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
263against a /placeholder/:
264
265 bind(&X::name, _1) == _2
266
267or 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]