«Int size = 10;» дает постоянное выражение?

Следующий код компилируется под gcc 4.8 и Clang 3.2:

int main() { int size = 10; int arr[size]; } 

8.3.4 / 1 стандарта C ++ говорит, что размер массива должен быть интегральным постоянным выражением, size которого, похоже, не является. Это ошибка в обоих компиляторах, или я чего-то не хватает?

Последний VC ++ CTP отклоняет код с помощью этого интересного сообщения:

 error C2466: cannot allocate an array of constant size 0 

Интересная часть состоит в том, как кажется, что size равен нулю. Но, по крайней мере, он отвергает код. Разве gcc и Clang не должны делать то же самое?

Это массивы переменной длины или VLA, которые являются функциями C99, но gcc и clang поддерживают его как расширение в C ++, а Visual Studio этого не делает . Таким образом, Visual Studio придерживается стандарта в этом случае и технически корректна. Не говоря уже о том, что расширения плохие, kernel Linux зависит от многих расширений gcc , поэтому они могут быть полезны в определенных контекстах.

Если вы добавите флаг -pedantic gcc и clang предупредит вас об этом, например gcc говорит ( см. -pedantic прямом эфире ):

 warning: ISO C++ forbids variable length array 'arr' [-Wvla] int arr[size]; ^ 

Использование -pedantic-errors приведет к ошибке. Вы можете больше узнать о расширениях в этих документах. Языковые стандарты, поддерживаемые GCC и clangs Language Compatibility .

Обновить

Проект стандарта C ++ охватывает то, что является интегральным постоянным выражением в разделе 5.19 Константные выражения, параграф 3, и гласит:

Интегральное постоянное выражение представляет собой выражение интегрального или неперечисленного типа enums, неявно преобразованного в prvalue, где преобразованное выражение является выражением постоянной константы. […]

Это не является интуитивно очевидным из чтения этого, что все возможности, но Boost’s Coding Guidelines для Integral Constant Expressions отлично справляется с этим.

В этом случае, поскольку вы инициализируете size с помощью литерала, используя const , достаточно сделать его интегральным постоянным выражением (см. [Expr.const] p2.9.1 ), а также вернуть код в стандартную C ++ :

 const int size = 10; 

использование constexpr тоже будет работать:

 constexpr int size = 10; 

Вероятно, это поможет прочитать разницу между constexpr и const .

Для справки эквивалентный раздел к пункту 8.3.4 пункта 1 в стандартном проекте 6.7.5.2 будет раздел 6.7.5.2 Объявление декларатора массива, пункт 4, в котором говорится ( основное внимание ):

Если размер отсутствует, тип массива является неполным. Если размер равен * вместо выражения, тип массива представляет собой массив массивов переменной длины неопределенного размера, который может использоваться только в объявлениях с областью прототипа функции; 124), такие массивы, тем не менее, являются полными типами. Если размер представляет собой целочисленное константное выражение, а тип элемента имеет известный постоянный размер, тип массива не является массивом переменной длины; в противном случае тип массива представляет собой тип массива переменной длины .

Давайте будем гением компьютера.