| [/ |
| / 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<R>(f, ...)`] |
| |
| The `bind<R>(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<R>(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 |
| [@http://www.sgi.com/tech/stl/UnaryFunction.html /Unary Function/] or |
| [@http://www.sgi.com/tech/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 |
| `<boost/bind/make_adaptable.hpp>`], which must be included explicitly in |
| addition to [@../../../../boost/bind.hpp `<boost/bind.hpp>`]: |
| |
| #include <boost/bind/make_adaptable.hpp> |
| |
| template <class R, class F> ``/unspecified-type/`` make_adaptable(F f); |
| |
| template<class R, class A1, class F> ``/unspecified-unary-functional-type/`` make_adaptable(F f); |
| |
| template<class R, class A1, class A2, class F> ``/unspecified-binary-functional-type/`` make_adaptable(F f); |
| |
| template<class R, class A1, class A2, class A3, class F> ``/unspecified-ternary-functional-type/`` make_adaptable(F f); |
| |
| template<class R, class A1, class A2, class A3, class A4, class F> ``/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<char_t>& ct = std::use_facet<std::ctype<char_t> >(loc); |
| |
| auto isntspace = std::not1(boost::make_adaptable<bool, char_t>(boost::bind(&std::ctype<char_t>::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 `boostbind` is brought into scope with an |
| using declaration: |
| |
| using boost::bind; |
| |
| the syntax `bind<R>(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<R>(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<R>(), 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<int>(printf, "%s\n", _1); |
| |
| [endsect] |
| |
| [endsect] |