Std::tuple sizeof, это пропущенная оптимизация?

Я проверил все основные компиляторы, и sizeof(std::tuple<int, char, int, char>) составляет 16 для всех них. Предположительно они просто приводят элементы в порядок в кортеже, поэтому некоторое пространство теряется из-за выравнивания.

Если кортеж хранимых элементов внутренне похож на: int, int, char, char, то его размер может быть 12.

Возможно ли для реализации сделать это, или это запрещено каким-то правилом в стандарте?

Ответ 1

std::tuple sizeof, is it a missed optimization?

Да.

Возможно ли для реализации сделать это [?]

Да.

[Это] запрещено каким-либо правилом в стандарте?

Неа!

Читая [tuple], на реализацию не накладывается никаких ограничений для хранения членов в порядке аргументов шаблона.

Фактически, каждый отрывок, который я могу найти, кажется, идет на все, чтобы вообще не ссылаться на порядок объявления членов: get<N>() используется в описании операционной семантики. Другая формулировка сформулирована в терминах "элементов", а не "членов", что выглядит как преднамеренная абстракция.

На самом деле, некоторые реализации, по-видимому, хранят члены в обратном порядке, по крайней мере, вероятно, просто из-за того, что они рекурсивно используют наследование для распаковки аргументов шаблона (и потому что, как и выше, им разрешено).

Говоря конкретно о вашей гипотетической оптимизации, я не знаю ни одной реализации, которая не хранит элементы в [некоторой тривиальной функции] заданного пользователем порядка; Я предполагаю, что было бы "сложно" придумать такой заказ и предоставить оборудование для std::get, по крайней мере, по сравнению с величиной прибыли, которую вы получили бы от этого. Если вы действительно обеспокоены заполнением, вы, конечно, можете тщательно выбирать порядок элементов, чтобы избежать его (на определенной платформе), как если бы вы использовали класс (не углубляясь в мир "упакованных" атрибутов). ("Упакованный" кортеж может быть интересным предложением & hellip;)

Ответ 2

Да, это возможно и было (в основном) сделано R. Мартиньо Фернандес. У него был блог под названием Flaming Danger Zone, который по какой-то причине сейчас недоступен, но его источники по-прежнему доступны на github.

Вот все четыре части серии "Вопросы размера" на эту тему: 1, 2, 3, 4.

Возможно, вы захотите просмотреть их в необработанном виде, так как github не понимает используемую разметку выделения C++ и отображает фрагменты кода как нечитаемые однослойные.

Он по существу вычисляет перестановку для индексов кортежей с помощью шаблонной метапрограммы C++ 11, которая сортирует элементы по выравниванию в не возрастающем порядке, сохраняет элементы в соответствии с ним, а затем применяет его к индексу при каждом доступе.

Ответ 3

Еще одна причина не делать этого: некоторые архитектуры, в том числе x86, имеют режим индексации, который может адресовать базу адреса + размер × индекс в одной инструкции, но только когда размер равен степени 2. Или загрузка может быть немного быстрее или сохранить в соответствии с 16-байтовой границей. Это может сделать код, который обращается к массивам std::tuple, немного быстрее и компактнее, если они добавят четыре байта заполнения.