27

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?

1 Answer 1

28

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)

Sign up to request clarification or add additional context in comments.

15 Comments

GCC 4.8 seems to do it differently (or the libstdc++ coming with it), since sizeof(std::array<int,0>) == 1. But I realize you said "one possible implementation" and I accept the reasoning, so thanks!
GCC does value_type _M_instance[_Nm ? _Nm : 1]; and I see sizeof(array<int,0>) == sizeof(int)
I see sizeof(std::array<int,0>) == 1 for GCC 4.8 on LiveWorkSpace.org. Strange.
Ah yes, I forgot it changed for GCC 4.8 to allow zero-sized arrays of non-DefaultConstructible types, see gcc.gnu.org/PR53248 (when gcc.gnu.org is back online). It now has an empty struct member instead of value_type[1].
I just found §23.3.2.1/2 from the standard. Doesn't that mean that it's not just an implementation detail and that the standard does say something about std::array<T,0>'s emptiness (although indirectly)? As a consequence, if I read it correctly, an empty implementation would even be illegal, wouldn't it?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.