std::bind

From cppreference.com
< cpp‎ | utility‎ | functional
Utilities library
Function objects
Function invocation
(C++17)(C++23)
Identity function object
(C++20)
Transparent operator wrappers
(C++14)
(C++14)
(C++14)
(C++14)  
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)

Old binders and adaptors
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)  
(until C++17*)
(until C++17*) (until C++17*) (until C++17*) (until C++17*)
(until C++20*)
(until C++20*)
(until C++17*)(until C++17*)
(until C++17*)(until C++17*)

(until C++17*)
(until C++17*) (until C++17*) (until C++17*) (until C++17*)
(until C++20*)
(until C++20*)
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 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 type with nested typedef result_type, then result_type is F::result_type. Otherwise no result_type
2) (deprecated in C++17) result_type is exactly R.
(until C++20)

Member function operator()

When g is invoked in a function call expression g(u1, u2, ... uM)

1) INVOKE (fd, std::forward <V1> (v1), std::forward <V2> (v2), ..., std::forward <VN> (vN) )
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

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 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)
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)