I study the generic lambdas, and slightly modified the example,
so my lambda should capture the upper lambda's variadic parameter pack.
So basically what is given to upper lambda as (auto&&...)
- should be somehow captured in [=]
block.
(The perfect forwarding is another question, I'm curious is it possible here at all?)
#include <iostream>
#include<type_traits>
#include<utility>
// base case
void doPrint(std::ostream& out) {}
template <typename T, typename... Args>
void doPrint(std::ostream& out, T && t, Args && ... args)
{
out << t << " "; // add comma here, see below
doPrint(out, std::forward<Args&&>(args)...);
}
int main()
{
// generic lambda, operator() is a template with one parameter
auto vglambda = [](auto printer) {
return [=](auto&&... ts) // generic lambda, ts is a parameter pack
{
printer(std::forward<decltype(ts)>(ts)...);
return [=] { // HOW TO capture the variadic ts to be accessible HERE ↓
printer(std::forward<decltype(ts)>(ts)...); // ERROR: no matchin function call to forward
}; // nullary lambda (takes no parameters)
};
};
auto p = vglambda([](auto&&...vars) {
doPrint(std::cout, std::forward<decltype(vars)>(vars)...);
});
auto q = p(1, 'a', 3.14,5); // outputs 1a3.14
//q(); //use the returned lambda "printer"
}
Perfect capture in C++20
C++17 and C++14 workaround
In C++17 we can use a workaround with tuples:
Unfortunately
std::apply
is C++17, in C++14 you can implement it yourself or do something similar withboost::hana
:It might be usefull to simplify the workaround by a function
capture_call
:Use it like this:
Here is a C++14 implementation of
capture_call
:capture_call
captures variables by value. The perfect means that the move constructor is used if possible. Here is a C++17 code example for better understanding:Output:
The type of the capture value contains
&&
in thecapture_call
version because we have to access the value in the internal tuple via reference, while a language supported capture supports direct access to the value.Well... it seems to me that the perfect forwarding is the question.
The capture of
ts...
works well and if you change, in the inner lambda,with
the program compile.
The problem is that capturing
ts...
by value (using[=]
) they becomeconst
values andprinter()
(that is a lambda that receiveauto&&...vars
) receive references (&
or&&
).You can see the same problem with the following functions
From clang++ I get
Another way to solve your problem is capture the
ts...
as references (so[&]
) instead as values.