In this article we will see how to use std::bind and when to use.
std::bind
std::bind is a Standard Function Objects that acts as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged.
Suppose We have a function to add two numbers i.e.
int add(int first, int second) { return first + second; }
std::bind takes a function as its first parameter and then that function’s argument as its parameter.
auto add_func = std::bind(&add, _1, _2);
Here add_func is a function object i.e. equivalent to add().
std::bind took the first parameter a function i.e. &add and then its arguments as _1 & _2 as his own arguments.
So, whenever we call this new function object i.e.
Frequently Asked:
add_func(4,5);
It will internally call the add() function and pass the first parameter at the place of _1 and second at the place of _2.
So, add_func(4,5) is equivalent to add(4,5).
[showads ad=inside_post]
Now suppose we want to use this add function in a special scenarion where we should fix the first argument to 12 always and let the second argument passed by user i.e.
int x = new_add_func(5); // Will return 9
We can do this using std::bind,
auto new_add_func = std::bind(&add, 12, _1);
So, when we call new_add_func(5) it will internally call the add() function with first parameter will be 12 always and second parameter will 5 i.e. passed as argument.
We can also rearrange arguments using std::bind() i.e. _1 and _2 etc decides the place of argument to be passed i.e.
auto mod_add_func = std::bind(&add, _2, _1);
When we call mod_add_func(12,15) it is equivalent to calling add(15, 12).
_1 represents the first passed argument and _2 second passed argument. Now while constructing new function object through std::bind we changed the order of arguments by passing _2 first and _1 second in the underlined function.
Use of std::bind in STL algorithms
As std::bind acts as a functional adaptor and gives the a new function objects, hence it is very usefull with many STL algorithms.
For example,
We have a list of numbers and we want to count the numbers which are multiple of 5. To achive this we have an existing function i.e.
bool divisible(int num , int den) { if(num % den == 0) return true; return false; }
First basic approach to this problem is lets iterate through all elements using for loop, check condition and increment counter i.e.
int approach_1() { int arr[10] = {1,20,13,4,5,6,10,28,19,15}; int count = 0; for(int i = 0; i < sizeof(arr)/sizeof(int); i++) { if(divisible(arr[i], 5)) count++; } return count; }
But this all is done in std::count_if STL algorithm i.e. std::count_if
count_if (InputIterator firstValue, InputIterator lastValue, UnaryPredicate predFunctionObject);
std::count_if Returns the number of elements in the range [firstValue,lastValue) for which predFunctionObject is true.
Now to use this std::count_if in our scenario we need to convert divisible() into a Unary predicate i.e. Fixing second value in function divisible () to 5 always. Let’s do this with std::bind,
int approach_2() { int arr[10] = {1,20,13,4,5,6,10,28,19,15}; return std::count_if(arr, arr + sizeof(arr)/sizeof(int) , std::bind(&divisible, _1, 5)); }
Here, std::bind(&divisible, _1, 5) Will return a new Function Object that takes only One Argument and checks if it is divissble by 5 or not.
What std::bind returns ?
std::bind returns a function object. In above examples we have either save this new function object in auto variable or used it directly.
But we can also store them using std::function Function object i.e.
std::function<int (int) > mod_add_funcObj = std::bind(&add, 20, _1);
To checkout more on std::function, checkout our next Article.
Pointers in C/C++ [Full Course]
Complete executable code is as follows,
#include <memory> #include <functional> #include <iostream> #include <algorithm> using namespace std::placeholders; int add(int first, int second) { return first + second; } bool divisible(int num , int den) { if(num % den == 0) return true; return false; } int approach_1() { int arr[10] = {1,20,13,4,5,6,10,28,19,15}; int count = 0; for(int i = 0; i < sizeof(arr)/sizeof(int); i++) { if(divisible(arr[i], 5)) count++; } return count; } int approach_2() { int arr[10] = {1,20,13,4,5,6,10,28,19,15}; return std::count_if(arr, arr + sizeof(arr)/sizeof(int) , std::bind(&divisible, _1, 5)); } int main() { int x = add(4,5); // Will return 9 // What if we want to fix the first argument auto new_add_func = std::bind(&add, 12, _1); x = new_add_func(5); // Will return 17 std::cout<<x<<std::endl; auto mod_add_func = std::bind(&add, _2, _1); x = mod_add_func(12, 15); // Will return 27 std::cout<<x<<std::endl; std::function<int (int) > mod_add_funcObj = std::bind(&add, 20, _1); x = mod_add_funcObj(15); // Will return 35 std::cout<<x<<std::endl; std::cout<<approach_1()<<std::endl; std::cout<<approach_2()<<std::endl; return 0; }
in approch2 std::placeholders::_1 is required
int approch2()
{
std::array arr = {1,20,13,4,5,6,10,28,19,15};
return std::count_if(arr.begin(), arr.end(), std::bind(&divisible, std::placeholders::_1, 5));
}
sorry you have used
using namespace std::placeholders;
Please add example for class member function