Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I can not return initializer list from lambda

Tags:

Why this code is not valid?

auto foo = [] () {     return {1, 2};      }; 

However, this is valid since the initializer_list is used just to initialize a vector not to return itself:

auto foo = [] () -> std::vector<int> {     return {1, 2};      }; 

Why I can not return initializer_list? It could be useful. For example, a lambda that can be used to initialize a vector or a list or ... with some default values for something.

like image 308
Humam Helfawi Avatar asked Feb 12 '16 11:02

Humam Helfawi


1 Answers

Lambda return type deduction uses the auto rules, which normally would have deduced std::initializer_list just fine. However, the language designers banned deduction from a braced initializer list in a return statement ([dcl.spec.auto]/7):

If the deduction is for a return statement and the initializer is a braced-init-list ([dcl.init.list]), the program is ill-formed.

The reason for this is that std::initializer_list has reference semantics ([dcl.init.list]/6).
[]() -> std::initializer_list<int> { return {1, 2}; } is every bit as bad as
[]() -> const int & { return 1; }. The lifetime of the backing array of the initializer_list object ends when the lambda returns, and you are left with a dangling pointer (or two).

Demo:

#include <vector>  struct Noisy {     Noisy()  { __builtin_printf("%s\n", __PRETTY_FUNCTION__); }     Noisy(const Noisy&) { __builtin_printf("%s\n", __PRETTY_FUNCTION__); }     ~Noisy() { __builtin_printf("%s\n", __PRETTY_FUNCTION__); } };  int main() {     auto foo = []() -> std::initializer_list<Noisy> { return {Noisy{}, Noisy{}}; };     std::vector<Noisy> bar{foo()}; } 

Output:

Noisy::Noisy() Noisy::Noisy() Noisy::~Noisy() Noisy::~Noisy() Noisy::Noisy(const Noisy&) Noisy::Noisy(const Noisy&) Noisy::~Noisy() Noisy::~Noisy() 

Note how the copy constructors are called after all the Noisy objects created so far have been destroyed already.

like image 188
T.C. Avatar answered Sep 19 '22 18:09

T.C.