forked from boostorg/bind
Because the 'include' directory is deleted from the final release, all the header links break. Can currently see the broken links in the inspect report.
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
|
|
[@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]
|