Почему alignas() не принимает пакет параметров?

#c #c 11 #visual-c #g #clang

#c #c 11 #visual-c #g #clang

Вопрос:

Согласно cppreference.com


спецификатор alignas (начиная с C 11)

Задает требование выравнивания типа или объекта.

Синтаксис

выравнивание (выражение)
выравнивание (идентификатор типа)
выравнивание (пакет …)

  1. alignas(expression) должно быть целочисленным постоянным выражением, которое принимает значение нуля или допустимое значение для выравнивания или расширенного выравнивания.

  2. Эквивалентно alignas(alignof(type))

  3. Эквивалентно нескольким спецификаторам alignas, применяемым к одному и тому же объявлению, по одному для каждого члена пакета параметров, который может быть либо типом, либо нетиповым пакетом параметров.


Так почему же следующее не работает для g , clang или VC ?

 struct alignas(1, 4) A {};
  

или

 struct alignas(int, double) A {};
  

Это дефект?

Редактировать

По-видимому, это работает для g 8.2, а не для clang 8.0 или VC 19.20.27508.1, так что, похоже, это дефект, и компиляторы не догнали.

Редактировать

По-видимому, запуск компилятора MinGW g в оболочке cygwin bash вызывает странное поведение. Отлично работает при запуске в оболочке bash от MinGW. Итак, нет, это тоже не работает в g 8.2.

Комментарии:

1. GCC 8.2, похоже, отклоняет код.

2. @Fureeish, не для меня. Отлично работает на моем домашнем компьютере.

3. Можете ли вы поделиться своими флагами компиляции? И точный код? Можете ли вы вставить его в godbolt, выбрать те же параметры компилятора и указать, будет ли результат таким же?

4. Очень странно. Единственный параметр (кроме имени файла) Я использую is -std=c 17 , и файл содержит только struct alignas(1,4) A {}; struct alignas(int, double) B {};

5. В godbold он выдает ту же ошибку, что и другие. На моем домашнем компьютере нет сообщения. Конечно, он также не генерирует исполняемый файл. Должно быть, что-то не так с установкой?

Ответ №1:

1, 4 или int, double не являются пакетами параметров. Это будет примером пакета параметров, используемого в этом контексте:

 template <class... T>
struct Widget
{
  struct alignas(T...) A {};
};
  

Обратите внимание, что к одному и тому же объявлению можно применить несколько alignas спецификаторов, поэтому ваши примеры могут быть записаны как alignas(1) alignas(4) и alignas(int) alignas(double) соответственно.

Комментарии:

1. Хм, непонятно, почему они вводят конкретный alignas(pack...) синтаксис без добавления поддержки переменных для alignas(type-id, ...) or alignas(expression, ...) — это единственный такой синтаксический выбор, который я могу придумать. С одной стороны, у нас уже есть sizeof...(pack) (хотя это сильно отличается от sizeof(pack)... ), поэтому alignas...(pack) было бы ясно различие. И я не думаю alignas(T)... , что это было бы особенно запутанно, если мы уже добавляем такой синтаксический специальный корпус. Я предполагаю, что это какая-то причина «это проще для синтаксического анализатора»?

2. О, ну, моя первоначальная идея заключалась в том, чтобы сделать это template <typename Base, typename...Deriveds> struct alignas(T, Us...) {}; , что, как я думал, было бы правильно, но, учитывая, что это также не будет пакетом параметров, тогда да. Это раздражает.

3. @Adrian Но это выполнимо как template </*as before*/> struct alignas(T) alignas(U...) {};

4. @Adrian это, по-моему, было бы очень несовместимо с остальной частью C . Основная идея вариационных шаблонов заключается в том, что вы можете развернуть пакеты параметров в списки, разделенные запятыми, в тех местах, где это привело бы к созданию допустимой синтаксической конструкции, если бы вы только что написали такой список самостоятельно. Использование имени пакета параметров без его расширения будет означать, что вы что-то делаете с самим пакетом параметров, а не с его содержимым. Таким образом, alignas(Ts) должно быть прочитано как «выравнивание на основе выравнивания Ts «. Пакет параметров не имеет выравнивания, поэтому это не имеет смысла…

5. sizeof... это отдельный вид выражения sizeof, который применяется к самому пакету параметров (вот почему ... они появляются перед пакетом параметров, а не после, как в расширении пакета). Выравнивание не является свойством, которым обладают пакеты параметров. Таким образом alignas...(Ts) , это было бы семантически несовместимо с тем, что sizeof...(Ts) делает. Как было сказано выше, я думаю, имело бы смысл просто определить это alignas(A, B, C) и alignas(1, 2, 4) указать наиболее сильное выравнивание из параметров, приведенных в списке. Тогда alignas(Ts...) это соответствовало бы «нормальному» синтаксису…