std::bind(3) | C++ Standard Libary | std::bind(3) |
NAME¶
std::bind - std::bind
Synopsis¶
Defined in header <functional>
template< class F, class... Args > (since C++11)
/* unspecified */ bind( F&& f, Args&&... args ); (until
C++20)
template< class F, class... Args >
constexpr /* unspecified */ bind( F&& f, (since C++20)
Args&&... args ); (1)
template< class R, class F, class... Args > (since C++11)
/* unspecified */ bind( F&& f, Args&&... args ); (until
C++20)
template< class R, class F, class... Args > (2)
constexpr /* unspecified */ bind( F&& f, (since C++20)
Args&&... args );
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¶
Callable object (function object, pointer to
function, reference to function,
f - 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 result_type¶
1) (deprecated in C++17) If F is a pointer to function or a
pointer to
member function, result_type is the return type of F. If F is a class
(until C++20)
type with nested typedef result_type, then result_type is
F::result_type. Otherwise no result_type is defined.
2) (deprecated in C++17) result_type is exactly R.
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
1) INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ...,
std::forward<VN>(vN)), or
2) 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¶
// Run this code
#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
1. the bounded arguments
were not forwarded to fd 1. forwarded
LWG 2021 C++11 2. in case 2, the type of V_i 2. changed to
was std::result_of<T
std::result_of<T cv &(Uj&&...)>::type&&
cv (Uj...)>::type
See also¶
bind_front bind a variable number of arguments, in order, to a
function
bind_back object
(C++20) (function template)
(C++23)
_1, _2, _3, _4, ... placeholders for the unbound arguments in a std::bind
expression
(C++11) (constant)
mem_fn creates a function object out of a pointer to a member
(C++11) (function template)
2024.06.10 | http://cppreference.com |