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[@https://boost.org/sgi/stl/UnaryFunction.html /Unary Function/] or 171[@https://boost.org/sgi/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/bind.hpp `<boost/bind/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 `boost::bind` 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] 269