Brian Silverman | ce4aa8d | 2018-08-04 23:36:03 -0700 | [diff] [blame^] | 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/doc/html/smart_ptr.html#shared_ptr `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] |