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
If
std::decay
<Ti>
::
type
or any type in Args
is not MoveConstructible or Destructible
Parameters
f | - | Callable |
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
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
Member type
|
(until C++20) |
Member function operator()
When g is invoked in a function call expression g(u1, u2, ... uM)
INVOKE
(fd, std::forward
<V1>
(v1), std::forward
<V2>
(v2), ..., std::forward
<VN>
(vN)
)
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
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
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
Bound arguments
For each stored argument arg_i, the corresponding bound argument v_i in the INVOKE
or INVOKE<R>
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&
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
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
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
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 wasstd::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) |