Function template std::bind takes a function as input and generates a forwarding call wrapper. Calling this wrapper is equivalent to invoking input function with some of its arguments. A placeholder forwards argument to the calling function object returned by std::bind.
Syntax
std::bind is defined in functional header. Below is syntax
template <class Fn, class... Args> bind (Fn&& fn, Args&&... args); template <class Ret, class Fn, class... Args> bind (Fn&& fn, Args&&... args);
It returns a function object based on fn, where
- fn : A function object, pointer to function or pointer to member.
- args : List of arguments to bind. Argument can be either values, or placeholders.
Arguments of fn are bound to args. A argument may either be bound to a value or be a placeholder. If bound to a value, calling the returned function object will always use that value as argument. If bound to a placeholder, calling the returned function object forwards an argument passed to the call. Order of the passed argument is specified by the placeholder.
Returned function object returns the same type as fn. However a return type can be specified. If fn is a pointer to member, the first argument expected by the returned function is an object of the class *fn is a member (or a reference to it, or a pointer to it).
Placeholders
std::placeholders
namespace declares an unspecified number of objects: _1, _2, _3,…, which are used to specify placeholders in calls to std::bind. When the function object returned by bind is called, an argument with placeholder _1 is replaced by the first argument in the call, _2 is replaced by the second argument in the call, and so on.
When a call to bind is used as a subexpression in another call to bind, the placeholders are relative to the outermost bind expression.
Example
Below example demonstrate the use of std::bind and std::placeholders. std::bind can be used with member variable and member function as shown in below example.
#include <iostream> // std::cout #include <functional> // std::bind #include <memory> // std::make_shared using namespace std::placeholders; double divide (double x, double y) { return x/y; } 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 + 11; } struct MyPair { double a,b; MyPair(){ a = 37.0; b = 31.0; } MyPair(double _a, double _b){ a = _a; b = _b; } double multiply() { return a*b; } void print_sum(int n1, int n2) { std::cout << n1+n2 << '\n'; } }; int main () { // Function both argument are constant auto fo1 = std::bind (divide,10,2); std::cout << fo1() << '\n'; // Output : 5 // Function both second argument is constant auto fo2 = std::bind (divide,_1,2); std::cout << fo2(10) << '\n'; // Output : 5 // Returns y/x, as placeholders reversed auto fn_invert = std::bind (divide,_2,_1); std::cout << fn_invert(10,2) << '\n'; // Output : 0.2 MyPair p1 {13,17}; // Binding member function with placeholder auto bound_member_fn = std::bind (&MyPair::multiply,_1); std::cout << bound_member_fn(p1) << '\n'; // Output : 20 // Binding data member auto bound_member_data = std::bind (&MyPair::a,p1); std::cout << bound_member_data() << '\n'; // Output : 13 MyPair p2; // bind to a pointer to data member auto f1 = std::bind(&MyPair::a, _1); std::cout << f1(p2) << '\n'; // Output : 37 // Nested bind subexpressions share the placeholders auto f2 = std::bind(f, _3, std::bind(g, _1), _3, 4, 5); // Call to f(12, g(10), 12, 4, 5); f2(10, 11, 12); // Output : 12 21 12 4 5 // Smart pointers can be used to call members of the referenced objects, too std::cout << f1(std::make_shared<MyPair>(p2)) << '\n'; // Output : 37 // Bind to a pointer to member function auto f3 = std::bind(&MyPair::print_sum, &p1, 95, _1); f3(5); // Output : 100 }
std::bind is also used in partial function application. Let us assume that a function object f
takes 3 arguments. bind is used to create a new function object which only takes two arguments, defined as:
// Function with three argument void f(int a, int b, int c); // Function with two argument g(a,b) = f(a, 4, b);
Middle argument of f is already specified, and g takes two argument. We can use use std::bind to get g:
auto g = bind(f, _1, 4, _2);