Why is std::array< T, 0 > not empty?

c++, c++11, language-lawyer, stdarray

Solution

The standard doesn't say anything about whether `tuple` or `array` should be empty, what you're seeing are implementation details, but there's no reason to make `tuple<>` non-empty, whereas there is a good reason for `array<T, 0>` being non-empty, consider:

std::array<int, sizeof...(values)> = { { values... } };

When the parameter pack is empty you'd get:

std::array<int, 0> = { { } };

For the initializer to be valid the object needs a member, which cannot be `int[0]` because you can't have zero-sized arrays as members, so a possible implementation is `int[1]`

An implementation doesn't have to special case the whole array, it can just do:

T m_data[N == 0 ? 1 : N];

and all other members work exactly the same way (assuming `end()` is defined as `begin()+N`)

Problem

Given any `std::array< T, 0 >`, why is it not empty? I mean "empty" as in: ``` std::is_empty< std::array< int, 0 > >::value ``` ... returning `false`, and ``` #include <iostream> #include <tuple> #include <array> struct Empty {}; int main() { std::cout << sizeof(std::tuple<int>) << std::endl; std::cout << sizeof(std::tuple<int,Empty>) << std::endl; std::cout << sizeof(std::tuple<int,std::array<int,0>>) << std::endl; } ``` yields ``` 4 4 8 ``` This means that for `std::array<int,0>`, the empty base optimization (EBO) is not applied. This seem especially strange to me given that `std::tuple<>` (note: no template parameters) is empty, i.e., `std::is_empty<std::tuple<>>::value` does yield `true`. Question: Why is that, given that size `0` is already a special case for `std::array`? Is it intentional or an oversight in the standard?

Original source