Consider this sample of code:
#include <initializer_list>
#include <iostream>
int main()
{
    for(auto e: []()->std::initializer_list<int>{return{1,2,3};}())
        std::cout<<e<<std::endl;
    return 0;
}
I tried to compile it with g++ (gcc version 4.9.2 (Debian 4.9.2-10)) and the output is correct. In clang++ (Debian clang version 3.5.0-9 (tags/RELEASE_350/final) (based on LLVM 3.5.0)) output for example:
0
2125673120
32546
Where first line are always 0 and last two are "random".
It's error in clang or something else? I think that this sample of code is correct.
Update:
When the lambda function return type is something else (e.g. std::vector or std::array) this code works fine.
From C++11 8.5.4 List Initialization [dcl.init.list]:
5 An object of type
std::initializer_list<E>is constructed from an initializer list as if the implementation allocated an array ofNelements of typeE, whereNis the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E>object is constructed to refer to that array. If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.6 The lifetime of the array is the same as that of the
initializer_listobject.
The return statement of your lambda initializes a temporary std::initializer_list<int> and returns a copy thereof. This is all good, except that the lifetime of the array to which it refers ends at the end of the full-expression. Accessing the dead array through the initializer_list outside of the lambda results in undefined behavior.
An initializer_list isn't a container, it's a reference to a temporary container. If you try to use it like a container you're going to have a bad time.
In C++14 (quoting N4140) paragraph 6 was clarified to:
6 The array has the same lifetime as any other temporary object (12.2), except that initializing an
initializer_listobject from the array extends the lifetime of the array exactly like binding a reference to a temporary.
by the resolution of CWG issue 1290. This clarification makes it impossible to use an initializer_list as, e.g., a member variable which was the intention of C++11. Even in C++14, however, your program has undefined behavior.
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