With gcc 4.9 -std=c++14, I tried making a vector of lambdas:
vector<function<void ()>> v = {[]{cout << "foo";}, []{cout << "bar";}};
for (auto&& a: v) a();
And it worked pretty well. Then I tried passing the initializer list of lambdas to the range-based for directly:
for (auto&& a: {[]{cout << "foo";}, []{cout << "bar";}}) a();
And I got:
error: unable to deduce 'std::initializer_list<auto>&&' from '{<lambda closure object>main()::<lambda()>{}, <lambda closure object>main()::<lambda()>{}}'
Judging by the appearance of the error message, I made a wild guess that it is probably because "lambda closure object"s are built-in language terms, and not direct equivalents of std::function (so no real types).
What is the deeper cause of this? Also, could this be implementation-related, or is such behavior dictated by the specification?
Each lambda has its own unique type. So you may not build std::initializer_list from lambdas of different types.
According to the C++ Standard (5.1.2 Lambda expressions)
3 The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below.
Also
6 The closure type for a non-generic lambda-expression with no lambda-capture has a public non-virtual nonexplicit const conversion function to pointer to function with C++ language linkage (7.5) having the same parameter and return types as the closure type’s function call operator.
Each lamdba has its own type, so compiler cannot deduced the type of the initializer_list
.
You have to tell which type you want:
For each lambda:
As your lambda doesn't capture variables, you may decay them to pointer to function with +
as follow:
for (auto&& a: {+[]{std::cout << "foo";}, +[]{std::cout << "bar";}}) a();
using function<void()>
:
for (auto&& a: {std::function<void()>([]{std::cout << "foo";}),
std::function<void()>([]{std::cout << "bar";})}) a();
For the initializer_list:
for (auto&& a: std::initializer_list<std::function<void()>>{
[]{std::cout << "foo";},
[]{std::cout << "bar";}}) a();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With