forked from boostorg/bind
269 lines
8.6 KiB
Plaintext
269 lines
8.6 KiB
Plaintext
[/
|
|
/ 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
|
|
[@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
|
|
`<boost/bind/make_adaptable.hpp>`], which must be included explicitly in
|
|
addition to [@../../../../boost/bind/bind.hpp `<boost/bind/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 `boost::bind` 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]
|