элементов определяется следующим образом?
typedef __conditional_t<is_const<_Tp>::value, const char, char> _CharType;
struct _ArrayInStructT { _Tp __data_[1]; };
_ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)];
В libstdc++ он определен интереснее: это вовсе не массив, а пустой тип с перегруженным operator[] и operator _Tp*, но в общем получается так, что sizeof(std::array<int, 0>) в libc++ это 4 байт, а в libstdc++ это 1 байт.
Я просмотрел всю историю коммитов в <array> (libc++), но так и не понял, как смысл в том, что __data_ в _ArrayInStructT это _Tp, а не просто например какой-нибудь char, в чем прикольчик?
Равно как и не понимаю смысл тестов, что sizeof(std::array<T, 0>) должен быть равен sizeof(T[1]), таки почему, какой смысл?
Придерживаюсь мнения, что я что-то упускаю.
чтобы все специализации array обладали некоторыми гарантиями, например .data возвращает не nullptr, возвращает уникальный адрес, так то алигненный и тд
Кажется, будто дело не в этом. Значение data() unspecified, и в libc++ реализации этот __elems_ так то никак и не трогается в специализации для size == 0. В реализации от libstdc++ вовсе нет никаких alignas. Пролистываю стандарт — не понимаю, смотрю на соседнюю реализацию — тоже не понимаю, откуда они его выдумали, и зачем делают массив нулевой длины размеров в массив единичной длины.
Видимо, это какая-то глупость, чудом сохранившаяся со старых времён. Вестимо, обоснований со стороны стандарта я и не найду, и надо делать патч, чтобы сделать мир логичней и понятней...
Заслать патч можно, но примут вряд ли - изменение layout'а ломает ABI. Но выяснить, почему исторически именно так - хорошая мысль
Какой патч? Исторически вообще любой объект не нулевой длины :)
Обсуждают сегодня