std::function and std::bind were originally part of the Boost C++ Library, but they were incorporated into the C++11 standard.
std::function is a standard library template class that provides a very convenient wrapper for a simple function, a functor, a method, or a lambda expression.
For example, if programmers want to store several functions, methods, functors, or lambda expressions in a vector, they could write something like this:
#include <functional>
#include <iostream>
#include <string>
#include <vector>
void execute(const std::vector<std::function<void ()>>& fs)
{
for (auto& f : fs)
f();
}
void plain_old_func()
{
std::cout << "I'm an old plain function" << std::endl;
}
class functor final
{
public:
void operator()() const
{
std::cout << "I'm a functor" << std::endl;
}
};
int main()
{
std::vector<std::function<void ()>> x;
x.push_back(plain_old_func);
functor functor_instance;
x.push_back(functor_instance);
x.push_back([] ()
{
std::cout << "HI, I'm a lambda expression" << std::endl;
});
execute(x);
}
As it can be seen, in this declaration:
std::vector<std::function<void ()>> x;
a vector of functions is being declared. The void () part means that the functions stored there do not receive any arguments and do not return anything (i.e., they have void as the return type). If programmers wanted to define a function that receives two integers and returns an integer, they could declare std::function as:
int my_func(int a, int b) { return a + b; }
function<int (int, int)> f = my_func;
The standard library also includes a function called std::bind. std::bind is a template function that returns a std::function object which, as the name suggests, binds a set of arguments to a function.
In the first code example, the functions stored in the vector do not receive any arguments, but programmers might want to store a function that accepts arguments in the same vector. They can do this using std::bind.
Having this function:
void show_text(const std::string& t)
{
std::cout << "TEXT: " << t << std::endl;
}
How can it be added to the vector of functions in the first code listing (if even possible, because they have different signatures)? It can be added like this in the main() function:
std::function<void ()> f = std::bind(show_text, "Bound function");
x.push_back(f);
The code above shows that std::bind takes a pointer to a function (it can also be a lambda expression or a functor) and a list of parameters to pass to that function. As a result, std::bind returns a new function object with a different signature because all the parameters for the function have already been specified.
For example, this code:
#include <functional>
#include <iostream>
int multiply(int a, int b)
{
return a * b;
}
int main()
{
using namespace std::placeholders;
auto f = std::bind(multiply, 5, _1);
for (int i = 0; i < 10; i++)
{
std::cout << "5 * " << i << " = " << f(i) << std::endl;
}
return 0;
}
demonstrates another usage of std::bind. The first parameter is a pointer to the multiply function. The second parameter is the value passed as the first argument to multiply. The third parameter is called a “placeholder.” A placeholder specifies which parameter in the bound function will be filled by a runtime argument. Inside the for loop, f is called with only one parameter, and the second argument is provided dynamically.
Thanks to placeholders, even the order of arguments can be modified. For example:
#include <functional>
#include <string>
#include <iostream>
void show(const std::string& a, const std::string& b, const std::string& c)
{
std::cout << a << "; " << b << "; " << c << std::endl;
}
int main()
{
using namespace std::placeholders;
auto x = std::bind(show, _1, _2, _3);
auto y = std::bind(show, _3, _1, _2);
auto z = std::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
std::bind can also be used to wrap a method of a given object (i.e., an already instantiated one) into a function. For example, if programmers want to wrap the say_something method from the following struct:
struct Messenger
{
void say_something(const std::string& msg) const
{
std::cout << "Message: " << msg << std::endl;
}
};
into a std::function declared as follows:
using my_function = std::function<void (const std::string&)>;
The call to std::bind would look like this:
Messenger my_messenger; /* an actual instance of the class */
my_function
a_simple_function = std::bind(
&Messenger::say_something /* pointer to the method */,
&my_messenger, /* pointer to the object */,
std::placeholders::_1 /* placeholder for the first argument in the method, as usual */
);
a_simple_function("Hello"); // will invoke the method Messenger::say_something on the object my_messenger