Pack expansion of variadic list of types into initializer list of complex types – is it legal?

  • A+

I would like to "materialize" a variadic types list into an initializer_list of related values. For example, having an std::tuple of several std::integral_constant<T, x> get an std::initializer_list<T>{...}. In general case, I would like to get initializer_list of some complex type, like std::string.

But the following simple example gives me a crash when compiled by Clang (although it works with GCC, at least on Coliru), so I suspect UB (or bug in Clang):

template <class... Ts> std::initializer_list<const std::string> materialize() {     return {       std::to_string(Ts::value)...     }; }  void print_out() {    for (const auto & x : materialize<std::true_type, std::false_type>()) {       std::cout << x << "/n";    } } 

Live on Coliru

So, is such code legal? In C++11/14/17?


Two things about initializer_list:

Initializer lists may be implemented as a pair of pointers or pointer and length. Copying a std::initializer_list does not copy the underlying objects.


The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended. The storage for std::initializer_list is unspecified (i.e. it could be automatic, temporary, or static read-only memory, depending on the situation).

so in this line

return {       std::to_string(Ts::value)...     }; 

you are creating local array, initializer_list keeps pointer to the beginning / end of this array, when function goes out of scope you have dangling pointers.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: