]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/bind/doc/bind/troubleshooting.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / bind / doc / bind / troubleshooting.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:troubleshooting Troubleshooting]
11
12[section Incorrect number of arguments]
13
14In a `bind(f, a1, a2, ..., aN)` expression, the function object `f` must be
15able to take exactly N arguments. This error is normally detected at "bind
16time"; 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
27A common variation of this error is to forget that member functions have an
28implicit "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
45As in normal function calls, the function object that is bound must be
46compatible with the argument list. The incompatibility will usually be
47detected by the compiler at "call time" and the result is typically an error
48in `bind.hpp` on a line that looks like:
49
50 return f(a[a1_], a[a2_]);
51
52An 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
68The placeholder `_N` selects the argument at position `N` from the argument
69list passed at "call time." Naturally, it is an error to attempt to access
70beyond 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
80The error is usually reported in `bind.hpp`, at a line similar to:
81
82 return f(a[a1_]);
83
84When emulating `std::bind1st(f, a)`, a common mistake of this category is to
85type `bind(f, a, _2)` instead of the correct `bind(f, a, _1)`.
86
87[endsect]
88
89[section Inappropriate use of `bind(f, ...)`]
90
91The `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] causes automatic
92recognition of the type of `f`. It will not work with arbitrary function
93objects; `f` must be a function or a member function pointer.
94
95It is possible to use this form with function objects that define
96`result_type`, but only on compilers that support partial specialization and
97partial ordering. In particular, MSVC up to version 7.0 does not support this
98syntax for function objects.
99
100[endsect]
101
102[section Inappropriate use of `bind<R>(f, ...)`]
103
104The `bind<R>(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] supports
105arbitrary function objects.
106
107It is possible (but not recommended) to use this form with functions or member
108function pointers, but only on compilers that support partial ordering. In
109particular, MSVC up to version 7.0 does not fully support this syntax for
110functions and member function pointers.
111
112[endsect]
113
114[section Binding a nonstandard function]
115
116By default, the `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form]
117recognizes "ordinary" C++ functions and function pointers. [link
118bind.implementation.stdcall Functions that use a different calling convention],
119or 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
121nonstandard functions.
122
123On some platforms, extern "C" functions, like `std::strcmp`, are not
124recognized by the short form of `bind`.
125
126See also [link bind.implementation.stdcall `__stdcall` and `pascal` Support].
127
128[endsect]
129
130[section Binding an overloaded function]
131
132An attempt to bind an overloaded function usually results in an error, as
133there is no way to tell which overload was meant to be bound. This is a common
134problem with member functions with two overloads, const and non-const, as in
135this 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
148The ambiguity can be resolved manually by casting the (member) function
149pointer to the desired type:
150
151 int main()
152 {
153 boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1);
154 }
155
156Another, arguably more readable, alternative is to introduce a temporary
157variable:
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
169The 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,
172even when the function objects are unary or binary operations, because the
173function object types are missing public typedefs `result_type` and
174`argument_type` or `first_argument_type` and `second_argument_type`. In cases
175where these typedefs are desirable, however, the utility function
176`make_adaptable` can be used to adapt unary and binary function objects to
177these 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`]
180and [@http://en.cppreference.com/w/cpp/utility/functional/binary_negate `std::binary_negate`].
181
182The `make_adaptable` function is defined in [@../../../../boost/bind/make_adaptable.hpp
183`<boost/bind/make_adaptable.hpp>`], which must be included explicitly in
184addition 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
198This 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
206In this example, `bind` creates the "is a space" (unary) predicate. It is then
207passed to `make_adaptable` so that a function object modeling the /Unary
208Function/ 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
215Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with
216the 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
225Workaround: remove the `const` qualifier from the argument.
226
227[endsect]
228
229[section MSVC specific: `using boost::bind;`]
230
231On MSVC (up to version 7.0), when `boostbind` is brought into scope with an
232using declaration:
233
234 using boost::bind;
235
236the syntax `bind<R>(f, ...)` does not work. Workaround: either use the
237qualified 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
245On MSVC (up to version 7.0), a nested class template named `bind` will shadow
246the function template `boost::bind`, breaking the `bind<R>(f, ...)`syntax.
247Unfortunately, some libraries contain nested class templates named `bind`
248(ironically, such code is often an MSVC specific workaround.)
249
250The 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
256MSVC (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
258the current implementation) form:
259
260 bind(printf, "%s\n", _1);
261
262and will reject the correct version:
263
264 bind<int>(printf, "%s\n", _1);
265
266[endsect]
267
268[endsect]