Search code examples
c++c++11c++17initializer-liststructured-bindings

Why does std::initializer_list not support std::get<>, std::tuple_size and std::tuple_element


Why does std::initializer_list not support std::get<>, std::tuple_size and std::tuple_element? It is used a lot in constexpr expressions as is right now, for example,

std::max({1, 2, 3, 4, 5});

And if it did cool things like the following would be possible

auto [x, y] = {1, 2};

So why does std::initializer_list not support these? As far as I know there is no way to construct a std::initializer_list at runtime, so the size is always fixed by the user.


Below is an example of how one can get the size of an std::intializer_list<> at compile time

#include <iostream>
#include <initializer_list>

using std::cout;
using std::endl;

template <typename...>  struct WhichType;

template <typename Type>
constexpr int size_init_list(std::initializer_list<Type> il) {
    return il.end() - il.begin();
}

int main() {
    constexpr auto size = size_init_list({1, 2, 3});
    cout << static_cast<int>(std::integral_constant<int, size>{}) << endl;
    return 0;
}

Solution

  • Even though the size of a std::initializer_list is a compile-time constant, the size isn't part of the type. Every initializer list of ints has the same type, namely std::initializer_list<int>. And std::tuple_size<std::initializer_list<int>>::value can only have one possible value. So obviously it cannot be used to get the actual size of an initializer list. It makes no sense to define it at all.