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

Как он анализируется: создание неназванного временного списка с сохраненным списком инициализации

Недавно я снова столкнулся с обозначением

( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }

Как я помню, это разрешено как на C, так и на С++, но с помощью довольно разных языковых механизмов.

Я полагал, что в С++ формальный вид состоит в том, что он является конструкцией неназванного временного с помощью преобразования типа epxlicit type (T) cast-expression, которое сводится к static_cast, который строит объект через С++ 11 § 5.2.9/4:

" выражение e может быть явно преобразовано в тип T с использованием static_cast формы static_cast<T>(e), если декларация T t(e); является корректной, для некоторых изобретенная временная переменная T (8.5)

Однако синтаксис выражения-выражения определяется С++ 11 §5.4/2 как либо унарное выражение, либо рекурсивно, выражение ( type-id ) cast-expression, где единичный базовый регистр это сокращение до унитарного выражения.

И насколько я могу сказать, что сжатый init-list не является выражением?

Альтернативным представлением может быть то, что он преобразует явное преобразование типа через функциональную нотацию, С++ 11 §5.2.3/3,

" спецификатор простого типа или typename-спецификатор, за которым следует список бит-init, создает временную объект указанного типа

но насколько я могу сказать, что спецификатор простого типа может содержать круглые скобки, а спецификатор typename включает ключевое слово typename?

4b9b3361

Ответ 1

В C99 (ну, на самом деле N1256, который является предыдущим проектом) 6.5.2.5/4:

Постфиксное выражение, состоящее из имени типа в скобках, сопровождаемое списком инициализаций, заключенным в скобки, является составным литералом. Он предоставляет неназванный объект, значение которого задается в списке инициализаторов.

Некоторые компиляторы - как минимум g++ и clang - предоставляют C99 сложные литералы на С++ в качестве расширения. Семантически выражение

( const int[10] ){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }

является литералом типа const int[10]: decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }) на самом деле const int[10]. Хорошо заметьте:. Некоторые разногласия между версиями g++ о точном типе: версии g++ до 4.9 говорят, что decltype((const int[10]){ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }) - const int(&)[10]. Смотрите эту демонстрационную программу.

Вы можете добиться того же результата в стандартном С++ с явным преобразованием типов с помощью функциональной нотации, но вы должны определить псевдоним типа для типа массива, поскольку для функциональной нотации требуется спецификатор простого типа:

using foo = const int[10];
foo{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

или Общий шаблон псевдонима Xeo:

template <typename T>
using foo = T;
foo<const int[10]>{ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };