std:: bind
Defined in header
<functional>
|
||
template
<
class
F,
class
...
Args
>
/* unspecified */ bind ( F && f, Args && ... args ) ; |
(1) |
(since C++11)
(constexpr since C++20) |
template
<
class
R,
class
F,
class
...
Args
>
/* unspecified */ bind ( F && f, Args && ... args ) ; |
(2) |
(since C++11)
(constexpr since C++20) |
The function template
std::bind
generates a forwarding call wrapper for
f
. Calling this wrapper is equivalent to invoking
f
with some of its arguments
bound
to
args
.
If
std::
is_constructible
<
std::
decay
<
F
>
::
type
, F
>
::
value
is
false
, or
std::
is_constructible
<
std::
decay
<
Arg_i
>
::
type
, Arg_i
>
::
value
is
false
for any type
Arg_i
in
Args
, the program is ill-formed.
If
std::
decay
<
Ti
>
::
type
or any type in
Args
is not
MoveConstructible
or
Destructible
, the behavior is undefined.
Parameters
f | - | Callable object (function object, pointer to function, reference to function, pointer to member function, or pointer to data member) that will be bound to some arguments |
args | - |
list of arguments to bind, with the unbound arguments replaced by the
placeholders
_1
,
_2
,
_3
... of namespace
std::placeholders
|
Return value
A function object
g
of unspecified type
T
, for which
std::
is_bind_expression
<
T
>
::
value
is
true
. It has the following members:
std::bind return type
Member objects
The return type of
std::bind
holds a member object of type
std::
decay
<
F
>
::
type
constructed from
std::
forward
<
F
>
(
f
)
, and one object per each of
args...
, of type
std::
decay
<
Arg_i
>
::
type
, similarly constructed from
std::
forward
<
Arg_i
>
(
arg_i
)
.
Constructors
The return type of
std::bind
is
CopyConstructible
if all of its member objects (specified above) are CopyConstructible, and is
MoveConstructible
otherwise. The type defines the following members:
Member type
|
(until C++20) |
Member function
operator()
When g is invoked in a function call expression g ( u1, u2, ... uM ) , an invocation of the stored object takes place, as if by
INVOKE
(
fd,
std::
forward
<
V1
>
(
v1
)
,
std::
forward
<
V2
>
(
v2
)
, ...,
std::
forward
<
VN
>
(
vN
)
)
, or
INVOKE<R>
(
fd,
std::
forward
<
V1
>
(
v1
)
,
std::
forward
<
V2
>
(
v2
)
, ...,
std::
forward
<
VN
>
(
vN
)
)
,
where
fd
is a value of type
std::
decay
<
F
>
::
type
, the values and types of the bound arguments
v1
,
v2
, ...,
vN
are determined as specified
below
.
If some of the arguments that are supplied in the call to g ( ) are not matched by any placeholders stored in g , the unused arguments are evaluated and discarded.
An invocation of
operator
(
)
is
non-throwing
or is a
constant subexpression
(since C++20)
if and only if so is the underlying
INVOKE
operation.
operator
(
)
participates in overload resolution only if the
INVOKE
operation is well-formed when treated as an unevaluated operand.
If g is volatile -qualified, the program is ill-formed.
If
INVOKE
(
fd, w1, w2, ..., wN
)
can never be a valid expression for any possible values
w1
,
w2
, ...,
wN
, the behavior is undefined.
Bound arguments
For each stored argument
arg_i
, the corresponding bound argument
v_i
in the
INVOKE
or
INVOKE<R>
operation is determined as follows:
Case 1: reference wrappers
If
arg_i
is of type
std::
reference_wrapper
<
T
>
(for example,
std::ref
or
std::cref
was used in the initial call to
std::bind
), then
v_i
is
arg_i.
get
(
)
and its type
V_i
is
T&
: the stored argument is passed by reference into the invoked function object.
Case 2: bind expressions
If
arg_i
is of type
T
for which
std::
is_bind_expression
<
T
>
::
value
is
true
(for example, another
std::bind
expression was passed directly into the initial call to
std::bind
), then
std::bind
performs function composition: instead of passing the function object that the bind subexpression would return, the subexpression is invoked eagerly, and its return value is passed to the outer invokable object. If the bind subexpression has any placeholder arguments, they are shared with the outer bind (picked out of
u1
,
u2
, ...
). Specifically,
v_i
is
arg_i
(
std::
forward
<
Uj
>
(
uj
)
...
)
and its type
V_i
is
std::
result_of
<
T
cv
&
(
Uj
&&
...
)
>
::
type
&&
(until C++17)
std::
invoke_result_t
<
T
cv
&
, Uj
&&
...
>
&&
(since C++17)
(cv-qualification is the same as that of
g
).
Case 3: placeholders
If
arg_i
is of type
T
, for which
std::
is_placeholder
<
T
>
::
value
is not
0
(meaning, a placeholder such as
std::placeholders::_1, _2, _3, ...
was used as the argument to the initial call to
std::bind
), then the argument indicated by the placeholder (
u1
for
_1
,
u2
for
_2
, etc) is passed to the invokable object:
v_i
is
std::
forward
<
Uj
>
(
uj
)
and its type
V_i
is
Uj&&
.
Case 4: ordinary arguments
Otherwise,
arg_i
is passed to the invokable object as lvalue argument:
v_i
is simply
arg_i
and its type
V_i
is
T
cv
&
, where
cv
is the same cv-qualification as that of
g
.
Exceptions
Only throws if construction of
std::
decay
<
F
>
::
type
from
std::
forward
<
F
>
(
f
)
throws, or any of the constructors for
std::
decay
<
Arg_i
>
::
type
from the corresponding
std::
forward
<
Arg_i
>
(
arg_i
)
throws where
Arg_i
is the ith type and
arg_i
is the ith argument in
Args... args
.
Notes
As described in Callable , when invoking a pointer to non-static member function or pointer to non-static data member, the first argument has to be a reference or pointer (including, possibly, smart pointer such as std::shared_ptr and std::unique_ptr ) to an object whose member will be accessed.
The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref .
Duplicate placeholders in the same bind expression (multiple _1 's for example) are allowed, but the results are only well defined if the corresponding argument ( u1 ) is an lvalue or non-movable rvalue.
Example
#include <functional> #include <iostream> #include <memory> #include <random> void f(int n1, int n2, int n3, const int& n4, int n5) { std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n'; } int g(int n1) { return n1; } struct Foo { void print_sum(int n1, int n2) { std::cout << n1 + n2 << '\n'; } int data = 10; }; int main() { using namespace std::placeholders; // for _1, _2, _3... std::cout << "1) argument reordering and pass-by-reference: "; int n = 7; // (_1 and _2 are from std::placeholders, and represent future // arguments that will be passed to f1) auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n); n = 10; f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused // makes a call to f(2, 42, 1, n, 7) std::cout << "2) achieving the same effect using a lambda: "; n = 7; auto lambda = [&ncref = n, n](auto a, auto b, auto /*unused*/) { f(b, 42, a, ncref, n); }; n = 10; lambda(1, 2, 1001); // same as a call to f1(1, 2, 1001) std::cout << "3) nested bind subexpressions share the placeholders: "; auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5); f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5); std::cout << "4) bind a RNG with a distribution: "; std::default_random_engine e; std::uniform_int_distribution<> d(0, 10); auto rnd = std::bind(d, e); // a copy of e is stored in rnd for (int n = 0; n < 10; ++n) std::cout << rnd() << ' '; std::cout << '\n'; std::cout << "5) bind to a pointer to member function: "; Foo foo; auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); f3(5); std::cout << "6) bind to a mem_fn that is a pointer to member function: "; auto ptr_to_print_sum = std::mem_fn(&Foo::print_sum); auto f4 = std::bind(ptr_to_print_sum, &foo, 95, _1); f4(5); std::cout << "7) bind to a pointer to data member: "; auto f5 = std::bind(&Foo::data, _1); std::cout << f5(foo) << '\n'; std::cout << "8) bind to a mem_fn that is a pointer to data member: "; auto ptr_to_data = std::mem_fn(&Foo::data); auto f6 = std::bind(ptr_to_data, _1); std::cout << f6(foo) << '\n'; std::cout << "9) use smart pointers to call members of the referenced objects: "; std::cout << f6(std::make_shared<Foo>(foo)) << ' ' << f6(std::make_unique<Foo>(foo)) << '\n'; }
Output:
1) argument reordering and pass-by-reference: 2 42 1 10 7 2) achieving the same effect using a lambda: 2 42 1 10 7 3) nested bind subexpressions share the placeholders: 12 12 12 4 5 4) bind a RNG with a distribution: 0 1 8 5 5 2 0 7 7 10 5) bind to a pointer to member function: 100 6) bind to a mem_fn that is a pointer to member function: 100 7) bind to a pointer to data member: 10 8) bind to a mem_fn that is a pointer to data member: 10 9) use smart pointers to call members of the referenced objects: 10 10
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2021 | C++11 |
1. the bounded arguments
were not forwarded to fd 2. in case 2, the type of
V_i
was
std:: result_of < T cv ( Uj... ) > :: type |
1. forwarded
2. changed to std:: result_of < T cv & ( Uj && ... ) > :: type && |
See also
(C++20)
(C++23)
|
bind a variable number of arguments, in order, to a function object
(function template) |
(C++11)
|
placeholders for the unbound arguments in a
std::bind
expression
(constant) |
(C++11)
|
creates a function object out of a pointer to a member
(function template) |