Подтвердить что ты не робот

Почему std:: array <T, 0> не пуст?

Для любого std::array< T, 0 >, почему он не пуст? Я имею в виду "пустой", как в:

 std::is_empty< std::array< int, 0 > >::value

возврат false и

 #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;
 }

дает

 4
 4
 8

что означает, что для std::array<int,0> пустая оптимизация базы (EBO) не применяется.

Мне кажется особенно странным, что std::tuple<> (примечание: без параметров шаблона) пуст, т.е. std::is_empty<std::tuple<>>::value дает true.

Вопрос: Почему это, учитывая, что размер 0 уже является особым случаем для std::array? Является ли это преднамеренным или надзором в стандарте?

4b9b3361

Ответ 1

В стандарте ничего не говорится о том, что tuple или array должно быть пустым, то, что вы видите, - это детали реализации, но нет причин сделать tuple<> непустым, тогда как есть хороший причина для array<T, 0> непуста, рассмотрим:

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

Когда пакет параметров пуст, вы получите:

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

Для того чтобы инициализатор был действителен, объекту нужен член, который не может быть int[0], потому что вы не можете иметь массивы нулевого размера в качестве членов, поэтому возможная реализация - int[1]

В реализации нет специального случая для всего массива, он может просто сделать:

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

и все остальные члены работают точно так же (предполагая, что end() определяется как begin()+N)