C++11: std::function and std::bind

std::function and std::bind were born inside the Boost C++ Library, but they were incorporated into the new C++11 standard.

std::function is a STL template class that provides a very convenient wrapper to a simple function, to a functor or to a lambda expression.

For example, if you want to store several functions, functors or lambda expressions in a vector, you could write something like this:

#include <functional>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void execute(const vector<function<void ()>>& fs)
{
	for (auto& f : fs)
		f();
}

void plain_old_func()
{
	cout << "I'm an old plain function" << endl;
}

class functor
{
	public:
		void operator()() const
		{
			cout << "I'm a functor" << endl;
		}
};

int main()
{
	vector<function<void ()>> x;
	x.push_back(plain_old_func);
	
	functor functor_instance;
	x.push_back(functor_instance);
	x.push_back([] ()
	{
		cout << "HI, I'm a lambda expression" << endl;
	});
	
	execute(x);
}

As you can see, in this declaration:


vector<function<void ()>> x;

we are declaring a vector of functions. The void () part means that the functions do not receive any argument and have void as return type. If you would want to define a function that receives two integers and return an integer too, you should declare your function as:

int my_func(int a, int b) { return a + b; }

function<int (int, int)> f = my_func;

The new standard library also adds a new function: std::bind. std::bind is a template function that returns a std::function object that binds a set of arguments to a function.

Consider the first code listing shown in this post, the functions stored in the vector do not receive any argument; but you probably want to store a function that receives more arguments in the same vector. You could do that using std::bind.

Say you have this function:

void show_text(const string& t)
{
	cout << "TEXT: " << t << endl;
}

How can you add it into the function of vectors of the first code listing? Add this code the main function:

function <void ()> f = bind(show_text, "Bound function");
x.push_back(f);	

As you can see, the std::bind receives a pointer to a function (it also can be a lambda expression or a functor) and receives a list of parameters that pass it to the function. As result, bind returns a new function object with a different prototype because all the parameters of the function were already specified.

Look at this code:

#include <functional>
#include <iostream>

using namespace std;
using namespace std::placeholders;

int multiply(int a, int b)
{
	return a * b;
}

int main()
{
	auto f = bind(multiply, 5, _1);
	for (int i = 0; i < 10; i++)
	{
		cout << "5 * " << i << " = " << f(i) << endl;
	}
        return 0;
}

Look at the usage of std::bind: The first parameter is the pointer to the function multiply. The second parameter is the value passed as first parameter to the function multiply. The third parameter is called a “placeholder”. A placeholder is an object that specifies the number of parameter in the bound function that will be used to enter this parameter. So, if you look inside the for loop, you can call f just passing it one parameter.

Thanks to the placeholders, you can change the order of the arguments passed as parameters to a bound function. For example:

#include <functional>
#include <string>
#include <iostream>

using namespace std;
using namespace std::placeholders;

void show(const string& a, const string& b, const string& c)
{
	cout << a << "; " << b << "; " << c << endl;
}

int main()
{
	auto x = bind(show, _1, _2, _3);
	auto y = bind(show, _3, _1, _2);
	auto z = bind(show, "hello", _2, _1);
	
	x("one", "two", "three");
	y("one", "two", "three");
	z("one", "two");
	
	return 0;
}

The output is:


one; two; three
three; one; two
hello; two; one

Advertisements

21 thoughts on “C++11: std::function and std::bind

  1. wow.. this is the most lucid explanation of c++11 concepts I have seen . Thanks for it.

  2. I’d nailed down std::function and lambdas, but struggled with the std::bind syntax and what _1 actually meant. This is by far the clearest explanation I’ve found so far. Good work sir. :)

  3. Probably the best and simples explanation on the net! Thanks.

    However. you *should* add info about the member function invocation using bind.
    The fact that you can bind the hidden ‘this’ argument and transform a member function into a regular one!

  4. this article was very useful in understanding the use of the placeholders with std::bind. I’d like to point that there is an little error in line (The second parameter is called a “placeholder”), as it should read (The third parameter …..)

    Thanks!

  5. Very good explanation. I didn’t understand anything about bind when I read about it in the C++ Primer (5th Edition) book. But this made it all clear to me!

  6. very good articles especially for beginner of c++11 like me. Thanks a lot.

    can you also explain one doubt

    1| function f = bind(show_text, “Bound function”);
    2| x.push_back(f);

    function
    function-type given to std::function is type-mismatched at line 1?
    If yes, then how we can insert it into vector.

    can you explain this please?

    Again thanks a lot for this concise and clear articles.

    1. Vivek, thanks for your nice comments.

      I reviewed my code in the example and void() is the right parameterized type for the bound function. Remember, bind() “hard codes” the “Bound function” and thus, there is no need to pass any parameter anymore. “Bind” does something like: auto f = []() { show_text(“Bound function”); };

  7. Cool, so you can achieve currying like in functional programming languages ? Even more flexible with the potential reordering of parameters. Is that right ?

  8. Thanx a lot… This will help me Finish my 1st Assignment of the course “High End Simulation Practice:-)”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s