]>
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:troubleshooting Troubleshooting] | |
11 | ||
12 | [section Incorrect number of arguments] | |
13 | ||
14 | In a `bind(f, a1, a2, ..., aN)` expression, the function object `f` must be | |
15 | able to take exactly N arguments. This error is normally detected at "bind | |
16 | time"; in other words, the compilation error is reported on the line where | |
17 | `bind()` is invoked: | |
18 | ||
19 | int f(int, int); | |
20 | ||
21 | int main() | |
22 | { | |
23 | boost::bind(f, 1); // error, f takes two arguments | |
24 | boost::bind(f, 1, 2); // OK | |
25 | } | |
26 | ||
27 | A common variation of this error is to forget that member functions have an | |
28 | implicit "this" argument: | |
29 | ||
30 | struct X | |
31 | { | |
32 | int f(int); | |
33 | } | |
34 | ||
35 | int main() | |
36 | { | |
37 | boost::bind(&X::f, 1); // error, X::f takes two arguments | |
38 | boost::bind(&X::f, _1, 1); // OK | |
39 | } | |
40 | ||
41 | [endsect] | |
42 | ||
43 | [section The function object cannot be called with the specified arguments] | |
44 | ||
45 | As in normal function calls, the function object that is bound must be | |
46 | compatible with the argument list. The incompatibility will usually be | |
47 | detected by the compiler at "call time" and the result is typically an error | |
48 | in `bind.hpp` on a line that looks like: | |
49 | ||
50 | return f(a[a1_], a[a2_]); | |
51 | ||
52 | An example of this kind of error: | |
53 | ||
54 | int f(int); | |
55 | ||
56 | int main() | |
57 | { | |
58 | boost::bind(f, "incompatible"); // OK so far, no call | |
59 | boost::bind(f, "incompatible")(); // error, "incompatible" is not an int | |
60 | boost::bind(f, _1); // OK | |
61 | boost::bind(f, _1)("incompatible"); // error, "incompatible" is not an int | |
62 | } | |
63 | ||
64 | [endsect] | |
65 | ||
66 | [section Accessing an argument that does not exist] | |
67 | ||
68 | The placeholder `_N` selects the argument at position `N` from the argument | |
69 | list passed at "call time." Naturally, it is an error to attempt to access | |
70 | beyond the end of this list: | |
71 | ||
72 | int f(int); | |
73 | ||
74 | int main() | |
75 | { | |
76 | boost::bind(f, _1); // OK | |
77 | boost::bind(f, _1)(); // error, there is no argument number 1 | |
78 | } | |
79 | ||
80 | The error is usually reported in `bind.hpp`, at a line similar to: | |
81 | ||
82 | return f(a[a1_]); | |
83 | ||
84 | When emulating `std::bind1st(f, a)`, a common mistake of this category is to | |
85 | type `bind(f, a, _2)` instead of the correct `bind(f, a, _1)`. | |
86 | ||
87 | [endsect] | |
88 | ||
89 | [section Inappropriate use of `bind(f, ...)`] | |
90 | ||
91 | The `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] causes automatic | |
92 | recognition of the type of `f`. It will not work with arbitrary function | |
93 | objects; `f` must be a function or a member function pointer. | |
94 | ||
95 | It is possible to use this form with function objects that define | |
96 | `result_type`, but only on compilers that support partial specialization and | |
97 | partial ordering. In particular, MSVC up to version 7.0 does not support this | |
98 | syntax for function objects. | |
99 | ||
100 | [endsect] | |
101 | ||
102 | [section Inappropriate use of `bind<R>(f, ...)`] | |
103 | ||
104 | The `bind<R>(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] supports | |
105 | arbitrary function objects. | |
106 | ||
107 | It is possible (but not recommended) to use this form with functions or member | |
108 | function pointers, but only on compilers that support partial ordering. In | |
109 | particular, MSVC up to version 7.0 does not fully support this syntax for | |
110 | functions and member function pointers. | |
111 | ||
112 | [endsect] | |
113 | ||
114 | [section Binding a nonstandard function] | |
115 | ||
116 | By default, the `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] | |
117 | recognizes "ordinary" C++ functions and function pointers. [link | |
118 | bind.implementation.stdcall Functions that use a different calling convention], | |
119 | or variable-argument functions such as `std::printf`, do not work. The general | |
120 | `bind<R>(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] works with | |
121 | nonstandard functions. | |
122 | ||
123 | On some platforms, extern "C" functions, like `std::strcmp`, are not | |
124 | recognized by the short form of `bind`. | |
125 | ||
126 | See also [link bind.implementation.stdcall `__stdcall` and `pascal` Support]. | |
127 | ||
128 | [endsect] | |
129 | ||
130 | [section Binding an overloaded function] | |
131 | ||
132 | An attempt to bind an overloaded function usually results in an error, as | |
133 | there is no way to tell which overload was meant to be bound. This is a common | |
134 | problem with member functions with two overloads, const and non-const, as in | |
135 | this simplified example: | |
136 | ||
137 | struct X | |
138 | { | |
139 | int& get(); | |
140 | int const& get() const; | |
141 | }; | |
142 | ||
143 | int main() | |
144 | { | |
145 | boost::bind(&X::get, _1); | |
146 | } | |
147 | ||
148 | The ambiguity can be resolved manually by casting the (member) function | |
149 | pointer to the desired type: | |
150 | ||
151 | int main() | |
152 | { | |
153 | boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1); | |
154 | } | |
155 | ||
156 | Another, arguably more readable, alternative is to introduce a temporary | |
157 | variable: | |
158 | ||
159 | int main() | |
160 | { | |
161 | int const& (X::*get) () const = &X::get; | |
162 | boost::bind(get, _1); | |
163 | } | |
164 | ||
165 | [endsect] | |
166 | ||
167 | [section Modeling STL function object concepts] | |
168 | ||
169 | The function objects that are produced by `bind` do not model the STL | |
170 | [@http://www.sgi.com/tech/stl/UnaryFunction.html /Unary Function/] or | |
171 | [@http://www.sgi.com/tech/stl/BinaryFunction.html /Binary Function/] concepts, | |
172 | even when the function objects are unary or binary operations, because the | |
173 | function object types are missing public typedefs `result_type` and | |
174 | `argument_type` or `first_argument_type` and `second_argument_type`. In cases | |
175 | where these typedefs are desirable, however, the utility function | |
176 | `make_adaptable` can be used to adapt unary and binary function objects to | |
177 | these concepts. This allows unary and binary function objects resulting from | |
178 | `bind` to be combined with STL templates such as | |
179 | [@http://en.cppreference.com/w/cpp/utility/functional/unary_negate `std::unary_negate`] | |
180 | and [@http://en.cppreference.com/w/cpp/utility/functional/binary_negate `std::binary_negate`]. | |
181 | ||
182 | The `make_adaptable` function is defined in [@../../../../boost/bind/make_adaptable.hpp | |
183 | `<boost/bind/make_adaptable.hpp>`], which must be included explicitly in | |
184 | addition to [@../../../../boost/bind.hpp `<boost/bind.hpp>`]: | |
185 | ||
186 | #include <boost/bind/make_adaptable.hpp> | |
187 | ||
188 | template <class R, class F> ``/unspecified-type/`` make_adaptable(F f); | |
189 | ||
190 | template<class R, class A1, class F> ``/unspecified-unary-functional-type/`` make_adaptable(F f); | |
191 | ||
192 | template<class R, class A1, class A2, class F> ``/unspecified-binary-functional-type/`` make_adaptable(F f); | |
193 | ||
194 | template<class R, class A1, class A2, class A3, class F> ``/unspecified-ternary-functional-type/`` make_adaptable(F f); | |
195 | ||
196 | template<class R, class A1, class A2, class A3, class A4, class F> ``/unspecified-4-ary-functional-type/`` make_adaptable(F f); | |
197 | ||
198 | This example shows how to use `make_adaptable` to make a predicate for "is not a space": | |
199 | ||
200 | typedef char char_t; | |
201 | std::locale loc(""); | |
202 | const std::ctype<char_t>& ct = std::use_facet<std::ctype<char_t> >(loc); | |
203 | ||
204 | auto isntspace = std::not1(boost::make_adaptable<bool, char_t>(boost::bind(&std::ctype<char_t>::is, &ct, std::ctype_base::space, _1))); | |
205 | ||
206 | In this example, `bind` creates the "is a space" (unary) predicate. It is then | |
207 | passed to `make_adaptable` so that a function object modeling the /Unary | |
208 | Function/ concept can be created, serving as the argument to | |
209 | [@http://en.cppreference.com/w/cpp/utility/functional/not1 `std::not1`]. | |
210 | ||
211 | [endsect] | |
212 | ||
213 | [section `const` in signatures] | |
214 | ||
215 | Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with | |
216 | the top-level `const` in function signatures: | |
217 | ||
218 | int f(int const); | |
219 | ||
220 | int main() | |
221 | { | |
222 | boost::bind(f, 1); // error | |
223 | } | |
224 | ||
225 | Workaround: remove the `const` qualifier from the argument. | |
226 | ||
227 | [endsect] | |
228 | ||
229 | [section MSVC specific: `using boost::bind;`] | |
230 | ||
231 | On MSVC (up to version 7.0), when `boostbind` is brought into scope with an | |
232 | using declaration: | |
233 | ||
234 | using boost::bind; | |
235 | ||
236 | the syntax `bind<R>(f, ...)` does not work. Workaround: either use the | |
237 | qualified name, `boost::bind`, or use an using directive instead: | |
238 | ||
239 | using namespace boost; | |
240 | ||
241 | [endsect] | |
242 | ||
243 | [section MSVC specific: class templates shadow function templates] | |
244 | ||
245 | On MSVC (up to version 7.0), a nested class template named `bind` will shadow | |
246 | the function template `boost::bind`, breaking the `bind<R>(f, ...)`syntax. | |
247 | Unfortunately, some libraries contain nested class templates named `bind` | |
248 | (ironically, such code is often an MSVC specific workaround.) | |
249 | ||
250 | The workaround is to use the alternative `bind(type<R>(), f, ...)` syntax. | |
251 | ||
252 | [endsect] | |
253 | ||
254 | [section MSVC specific: `...` in signatures treated as type] | |
255 | ||
256 | MSVC (up to version 7.0) treats the ellipsis in a variable argument function | |
257 | (such as `std::printf`) as a type. Therefore, it will accept the (incorrect in | |
258 | the current implementation) form: | |
259 | ||
260 | bind(printf, "%s\n", _1); | |
261 | ||
262 | and will reject the correct version: | |
263 | ||
264 | bind<int>(printf, "%s\n", _1); | |
265 | ||
266 | [endsect] | |
267 | ||
268 | [endsect] |