Целый размер = 10; получить постоянное выражение?

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

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

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

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

error C2466: cannot allocate an array of constant size 0

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


person KnowItAllWannabe    schedule 22.01.2014    source источник
comment
массив переменной длины - это только C, а не C++. однако gcc и clang поддерживают его как расширение.   -  person Bryan Chen    schedule 22.01.2014
comment
Может ли быть расширение для массивов переменной длины, предложенное в С++ 1y и/или C99?   -  person Yakk - Adam Nevraumont    schedule 22.01.2014
comment
std::valarray предлагается в C++1y   -  person Bryan Chen    schedule 22.01.2014
comment
@BryanChen, вы, вероятно, думаете о std::dynarray, но и это, и VLA находятся в TS AFAIK.   -  person chris    schedule 22.01.2014
comment
Это был один из наиболее плодотворных вопросов, на которые я ответил за последнее время. Пытаясь усилить свой ответ о постоянных выражениях, я обнаружил лакомый кусочек неопределенного поведения, который привел меня к этому вопросу и ответу Почему константные выражения имеют исключение для неопределенного поведения?.   -  person Shafik Yaghmour    schedule 27.01.2014
comment
size не является постоянным выражением, поскольку, среди прочего, его можно изменить.   -  person Keith Thompson    schedule 02.04.2014


Ответы (1)


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

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

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

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

Обновить

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

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

После прочтения этого интуитивно не очевидно, что все возможности, но Boost's Coding Guidelines for 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 в проект стандарта C99 будет разделом 6.7.5.2 Деклараторы массивов параграфом 4, в котором говорится (выделено мной):

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

person Shafik Yaghmour    schedule 22.01.2014