In this section, we are going to create several lambda expressions that are completely different in regard to the variable types they capture but have the same function call signature in common. These will be saved in one vector using std::function:
- Let's first do some necessary includes:
#include <iostream>
#include <deque>
#include <list>
#include <vector>
#include <functional>
- We implement a little function that returns a lambda expression. It accepts a container and returns a function object that captures that container by reference. The function object itself accepts an integer parameter. Whenever that function object is fed with an integer, it will append that integer to the container it captures:
static auto consumer (auto &container){
return [&] (auto value) {
container.push_back(value);
};
}
- Another little helper function will print whatever container instance we provide as a parameter:
static void print (const auto &c)
{
for (auto i : c) {
std::cout << i << ", ";
}
std::cout << 'n';
}
- In the main function, we first instantiate a deque, a list, and a vector, which all store integers:
int main()
{
std::deque<int> d;
std::list<int> l;
std::vector<int> v;
- Now we use the consumer function with our container instances, d, l, and v: we produce consumer function objects for those and store them all in a vector instance. Then we have a vector that stores three function objects. These function objects each capture a reference to one of the container objects. These container objects are of completely different types and so are the function objects. Nevertheless, the vector holds instances of std::function<void(int)>. All the function objects are implicitly wrapped into such std::function objects, which are then stored in the vector:
const std::vector<std::function<void(int)>> consumers
{consumer(d), consumer(l), consumer(v)};
- Now, we feed 10 integer values to all the data structures by looping over the values and then looping over the consumer function objects, which we call with those values:
for (size_t i {0}; i < 10; ++i) {
for (auto &&consume : consumers) {
consume(i);
}
}
- All the three containers should now contain the same 10 number values. Let's print their content:
print(d);
print(l);
print(v);
}
- Compiling and running the program yields the following output, which is just what we expect:
$ ./std_function
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,