Bind() introduced in c++11 allows you to bind parameters of a callable in a flexible way. You
can bind parameters to fixed values, and you can even rearrange parameters in a different order.
bind(function pointer, bound arguments)
For example, let add3 be a function that takes 3 integer arguments and returns an int that is the sum of its arguments: int add3(int a, int b, int c)
{
int sum = a+b+c;
cout << a << ‘+’ << b << ‘+’ << c << ‘=’ << sum << endl;
return sum;
}
Let int1, int2, and int3 be three int variables. Then bind(add3, int1, int2, int3) creates and returns a function object whose function call operator takes no arguments and calls add3 with the values in the three integer variables and returns an int.
Now, We can invoke the function call operator like below:
int result = bind(add3, int1, int2, int3)();
The final effect is as if add3 was called as:
int result = add3(int1, int2, int3);
When the function object is created, a pointer to the function is stored in a member variable(here it is add3), and the values in the bound arguments are copied into the function object and stored as member variable values. When the function call operator is executed, the saved pointer is used to call the function, and the saved values are supplied as arguments to that function.
Bind with placeholders
when we use the function object in a call, the final function arguments can be taken from a mixture of bound arguments and the arguments supplied in the call, which will be termed as the call arguments. This is done with special placeholders in the list of bound arguments.
Suppose you have a function called fun() accepting two arguments:
void fun(int num, std::string str)
{
cout << “fun(” << num << “, ” << str << “)” << endl;
}
The following code demonstrates how you can use bind() to bind the second argument of fun()
to a fixed value, str. The result is stored in func1().
The auto keyword is used because the return type of bind() is unspecified.
Arguments that are not bound to specific values should be specified as _1, _2, _3, and so on.
These are defined in the std::placeholders namespace. In the definition of func1(), the _1 specifies
where the first argument to func1() needs to go when fun() is called.
After this, func1() can be called with just a single integer argument.
std::string str = “abc”;
auto func1 = bind(fun, placeholders::_1, str);
func1(16);
Here is the output:
fun(16, abc)
bind can also be used to rearrange the arguments, as shown in the following code.
The _2 specifies where the second argument to func2() needs to go when fun() is called.
In other words, the func2() binding means that the first argument to func2() will become the
second argument to fun(), and the second argument to func2() will become the first
argument to fun().
auto func2 = bind(fun, placeholders::_2, placeholders::_1);
func2(“Test”, 2);
The output is as follows:
fun(2, Test)
Suppose you have function as follows:
void increment(int& val){ ++val; }
Now, if you call this function as follows, then value of index will be incremented to 1
int index = 0;
increment(index);
If you use bind() to call it as follows then the value of index is not incremented because a copy
of index is made, and a reference to this copy is bound to the first parameter of the increment()
function:
int index = 0;
auto incr = bind(increment, index);
incr();
Using std::ref() to pass a proper reference correctly increments index:
int index = 0;
auto incr = bind(increment, ref(index));
incr();
Issue with Binding
Suppose you have following two overloaded functions. One accepts an integer and the other
accepts a floating-point number:
void overloaded(int num) {}
void overloaded(float f) {}
If you want to use bind() with these overloaded functions, you need to explicitly specify which
of the two overloads you want to bind. The following will not compile:
auto func3 = bind(overloaded, placeholders::_1); // ERROR
If you want to bind the parameters of the overloaded function accepting a floating-point
argument, you need the following syntax:
auto func4 = bind((void(*)(float))overloaded, placeholders::_1); // OK
Binding with Algorithm
Consider find_if() algorithm to find the first element in a sequence that is greater than or equal
to 100. The following code uses bind() to bind the second parameter of greater_equal to a fixed
value of 100:
// Code for inputting scores into the vector omitted, similar as earlier.
vector<int> myVector {1,2,3,5,6}
auto endIter = end(myVector);
auto it = find_if(begin(myVector), endIter,
bind(greater_equal<>(), placeholders::_1, 100));
if (it == endIter) {
cout << “No perfect scores” << endl;
} else {
cout << “Found a \”perfect\” score of ” << *it << endl;
}
Hope you found this article useful.