Как он анализируется: создание неназванного временного списка с сохраненным списком инициализации
Недавно я снова столкнулся с обозначением
( 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
?
Ответы
Ответ 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 };