[/ / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. / Copyright (c) 2003-2008 Peter Dimov / / Distributed under the Boost Software License, Version 1.0. (See / accompanying file LICENSE_1_0.txt or copy at / http://www.boost.org/LICENSE_1_0.txt) /] [section:troubleshooting Troubleshooting] [section Incorrect number of arguments] In a `bind(f, a1, a2, ..., aN)` expression, the function object `f` must be able to take exactly N arguments. This error is normally detected at "bind time"; in other words, the compilation error is reported on the line where `bind()` is invoked: int f(int, int); int main() { boost::bind(f, 1); // error, f takes two arguments boost::bind(f, 1, 2); // OK } A common variation of this error is to forget that member functions have an implicit "this" argument: struct X { int f(int); } int main() { boost::bind(&X::f, 1); // error, X::f takes two arguments boost::bind(&X::f, _1, 1); // OK } [endsect] [section The function object cannot be called with the specified arguments] As in normal function calls, the function object that is bound must be compatible with the argument list. The incompatibility will usually be detected by the compiler at "call time" and the result is typically an error in `bind.hpp` on a line that looks like: return f(a[a1_], a[a2_]); An example of this kind of error: int f(int); int main() { boost::bind(f, "incompatible"); // OK so far, no call boost::bind(f, "incompatible")(); // error, "incompatible" is not an int boost::bind(f, _1); // OK boost::bind(f, _1)("incompatible"); // error, "incompatible" is not an int } [endsect] [section Accessing an argument that does not exist] The placeholder `_N` selects the argument at position `N` from the argument list passed at "call time." Naturally, it is an error to attempt to access beyond the end of this list: int f(int); int main() { boost::bind(f, _1); // OK boost::bind(f, _1)(); // error, there is no argument number 1 } The error is usually reported in `bind.hpp`, at a line similar to: return f(a[a1_]); When emulating `std::bind1st(f, a)`, a common mistake of this category is to type `bind(f, a, _2)` instead of the correct `bind(f, a, _1)`. [endsect] [section Inappropriate use of `bind(f, ...)`] The `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] causes automatic recognition of the type of `f`. It will not work with arbitrary function objects; `f` must be a function or a member function pointer. It is possible to use this form with function objects that define `result_type`, but only on compilers that support partial specialization and partial ordering. In particular, MSVC up to version 7.0 does not support this syntax for function objects. [endsect] [section Inappropriate use of `bind(f, ...)`] The `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] supports arbitrary function objects. It is possible (but not recommended) to use this form with functions or member function pointers, but only on compilers that support partial ordering. In particular, MSVC up to version 7.0 does not fully support this syntax for functions and member function pointers. [endsect] [section Binding a nonstandard function] By default, the `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] recognizes "ordinary" C++ functions and function pointers. [link bind.implementation.stdcall Functions that use a different calling convention], or variable-argument functions such as `std::printf`, do not work. The general `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] works with nonstandard functions. On some platforms, extern "C" functions, like `std::strcmp`, are not recognized by the short form of `bind`. See also [link bind.implementation.stdcall `__stdcall` and `pascal` Support]. [endsect] [section Binding an overloaded function] An attempt to bind an overloaded function usually results in an error, as there is no way to tell which overload was meant to be bound. This is a common problem with member functions with two overloads, const and non-const, as in this simplified example: struct X { int& get(); int const& get() const; }; int main() { boost::bind(&X::get, _1); } The ambiguity can be resolved manually by casting the (member) function pointer to the desired type: int main() { boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1); } Another, arguably more readable, alternative is to introduce a temporary variable: int main() { int const& (X::*get) () const = &X::get; boost::bind(get, _1); } [endsect] [section Modeling STL function object concepts] The function objects that are produced by `bind` do not model the STL [@https://boost.org/sgi/stl/UnaryFunction.html /Unary Function/] or [@https://boost.org/sgi/stl/BinaryFunction.html /Binary Function/] concepts, even when the function objects are unary or binary operations, because the function object types are missing public typedefs `result_type` and `argument_type` or `first_argument_type` and `second_argument_type`. In cases where these typedefs are desirable, however, the utility function `make_adaptable` can be used to adapt unary and binary function objects to these concepts. This allows unary and binary function objects resulting from `bind` to be combined with STL templates such as [@http://en.cppreference.com/w/cpp/utility/functional/unary_negate `std::unary_negate`] and [@http://en.cppreference.com/w/cpp/utility/functional/binary_negate `std::binary_negate`]. The `make_adaptable` function is defined in [@../../../../boost/bind/make_adaptable.hpp ``], which must be included explicitly in addition to [@../../../../boost/bind/bind.hpp ``]: #include template ``/unspecified-type/`` make_adaptable(F f); template ``/unspecified-unary-functional-type/`` make_adaptable(F f); template ``/unspecified-binary-functional-type/`` make_adaptable(F f); template ``/unspecified-ternary-functional-type/`` make_adaptable(F f); template ``/unspecified-4-ary-functional-type/`` make_adaptable(F f); This example shows how to use `make_adaptable` to make a predicate for "is not a space": typedef char char_t; std::locale loc(""); const std::ctype& ct = std::use_facet >(loc); auto isntspace = std::not1(boost::make_adaptable(boost::bind(&std::ctype::is, &ct, std::ctype_base::space, _1))); In this example, `bind` creates the "is a space" (unary) predicate. It is then passed to `make_adaptable` so that a function object modeling the /Unary Function/ concept can be created, serving as the argument to [@http://en.cppreference.com/w/cpp/utility/functional/not1 `std::not1`]. [endsect] [section `const` in signatures] Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with the top-level `const` in function signatures: int f(int const); int main() { boost::bind(f, 1); // error } Workaround: remove the `const` qualifier from the argument. [endsect] [section MSVC specific: `using boost::bind;`] On MSVC (up to version 7.0), when `boost::bind` is brought into scope with an using declaration: using boost::bind; the syntax `bind(f, ...)` does not work. Workaround: either use the qualified name, `boost::bind`, or use an using directive instead: using namespace boost; [endsect] [section MSVC specific: class templates shadow function templates] On MSVC (up to version 7.0), a nested class template named `bind` will shadow the function template `boost::bind`, breaking the `bind(f, ...)`syntax. Unfortunately, some libraries contain nested class templates named `bind` (ironically, such code is often an MSVC specific workaround.) The workaround is to use the alternative `bind(type(), f, ...)` syntax. [endsect] [section MSVC specific: `...` in signatures treated as type] MSVC (up to version 7.0) treats the ellipsis in a variable argument function (such as `std::printf`) as a type. Therefore, it will accept the (incorrect in the current implementation) form: bind(printf, "%s\n", _1); and will reject the correct version: bind(printf, "%s\n", _1); [endsect] [endsect]