Reputation: 56903
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?
Upvotes: 27
Views: 1851
Reputation: 171403
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
)
Upvotes: 28