While thinking about solution for question std::initializer list from already existing std::array without enumerating each element, I developed similar mechanism as bolov did, but not constructing the object, but rather only initializer list. I was surprised that my solution did not work and I couldn't figure out why.
#include <initializer_list>
#include <iostream>
#include <array>
template<typename T, std::size_t N, std::size_t... Is>
std::initializer_list<T> array_to_init_list_helper(std::array<T, N> arr, std::index_sequence<Is...>)
{
return {arr[Is]...};
}
template<typename T, std::size_t N>
std::initializer_list<T> array_to_init_list(std::array<T, N> arr)
{
return array_to_init_list_helper(arr, std::make_index_sequence<N>{});
}
int main()
{
std::array<int, 5> arr{1, 2, 3, 4, 5};
auto init_list = array_to_init_list(arr);
for (auto val : init_list)
std::cout << val << " ";
}
I am getting random values, while I would expect to get values of arr
.
Going through the assembly here (clang 4.0.0) and/or here (GCC 7.1), it is clear that the std::initializer_list
is using a dangling pointer, which (as we all know) produces seemingly random output.
EDIT
This result is of course in line with the comment made by Igor Tandetnik, quoting cppreference.com:
The underlying array is a temporary array of type const T[N], in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). The underlying array may be allocated in read-only memory.
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