We are going to write a lambda expression helper, which forwards a single call to multiple objects, and another lambda expression helper, which forwards a single call to multiple calls of other functions. In our example, we are going to use this to print a single message with different printer functions:
- Let's include the STL header we need for printing first:
#include <iostream>
- At first, we implement the multicall function, which is central to this recipe. It accepts an arbitrary number of functions as parameters and returns a lambda expression that accepts one parameter. It forwards this parameter to all the functions that were provided before. This way, we can define auto call_all (multicall(f, g, h)), and then, call_all(123) leads to a sequence of calls,f(123); g(123); h(123);. This function looks really complicated because we need a syntax trick in order to expand the parameter pack, functions, into a series of calls by using an std::initializer_list constructor:
static auto multicall (auto ...functions)
{
return [=](auto x) {
(void)std::initializer_list<int>{
((void)functions(x), 0)...
};
};
}
- The next helper accepts a function, f, and a pack of parameters, xs. What it does is it calls f with each of those parameters. This way, a for_each(f, 1, 2, 3) call leads to a series of calls: f(1); f(2); f(3);. This function essentially uses the same syntax trick to expand the parameter pack, xs, to a series of function calls, as the other function before:
static auto for_each (auto f, auto ...xs) {
(void)std::initializer_list<int>{
((void)f(xs), 0)...
};
}
- The brace_print function accepts two characters and returns a new function object, which accepts one parameter, x. It will print it, surrounded by the two characters we just captured before:
static auto brace_print (char a, char b) {
return [=] (auto x) {
std::cout << a << x << b << ", ";
};
}
- Now, we can finally put everything to use in the main function. At first, we define functions f, g, and h. They represent print functions that accept values and print them surrounded by different braces/parentheses each. The nl function takes any parameter and just prints a line break character:
int main()
{
auto f (brace_print('(', ')'));
auto g (brace_print('[', ']'));
auto h (brace_print('{', '}'));
auto nl ([](auto) { std::cout << 'n'; });
- Let's combine all of them using our multicall helper:
auto call_fgh (multicall(f, g, h, nl));
- For each of the numbers we provide, we want to see them individually printed three times surrounded by different pairs of braces/parentheses. This way, we can do a single function call and end up with five calls to our multifunction, which does another four calls to f, g, h, and nl.
for_each(call_fgh, 1, 2, 3, 4, 5);
}
- Before compiling and running, think about what output to expect:
$ ./multicaller
(1), [1], {1},
(2), [2], {2},
(3), [3], {3},
(4), [4], {4},
(5), [5], {5},