“Int size = 10;” produz uma expressão constante?

O código a seguir compila em gcc 4.8 e Clang 3.2:

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

8.3.4 / 1 do C ++ Standard diz que o tamanho de um array deve ser uma expressão constante integral, cujo size parece não ser. Isso é um bug em ambos os compiladores, ou estou faltando alguma coisa?

O último CTP VC ++ rejeita o código com esta mensagem interessante:

 error C2466: cannot allocate an array of constant size 0 

A parte interessante é como parece pensar que o size é zero. Mas pelo menos ele rejeita o código. O gcc e o Clang não deveriam fazer o mesmo?

Isso é matrizes de comprimento variável ou VLA, que é um recurso C99 , mas o gcc e o clang o suportam como uma extensão em C ++, enquanto o Visual Studio não . Portanto, o Visual Studio está aderindo ao padrão neste caso e está tecnicamente correto. Para não dizer que as extensões são ruins, o kernel do Linux depende de muitas extensões do gcc , então elas podem ser úteis em determinados contextos.

Se você adicionar a sinalização -pedantic o gcc e o clang avisarão sobre isso, por exemplo, o gcc diz ( veja ao vivo ):

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

Usar o -pedantic-errors fará com que isso seja um erro. Você pode ler mais sobre extensões nesses documentos Padrões de idioma Suportados pelo GCC e clangs na seção Compatibilidade de idiomas .

Atualizar

O esboço do padrão C ++ abrange o que é uma expressão constante integral na seção 5.19 Expressões constantes, parágrafo 3, e diz:

Uma expressão constante integral é uma expressão do tipo de enumeração integral ou sem escopo, implicitamente convertida em um prvalor, em que a expressão convertida é uma expressão constante central. […]

Não é intuitivamente óbvio ao ler isso que todas as possibilidades são, mas as Diretrizes de Codificação do Boost para Expressões Constantes Integrais fazem um ótimo trabalho.

Neste caso, uma vez que você está inicializando o size com um literal usando const seria suficiente torná-lo uma expressão constante integral (veja [expr.const] p2.9.1 ) e também trazer o código de volta ao padrão C ++ :

 const int size = 10; 

usar constexpr também funcionaria:

 constexpr int size = 10; 

Provavelmente ajudaria a ler Diferença entre constexpr e const .

Para referência, a seção equivalente a 8.3.4 parágrafo 1, no padrão de esboço C99 seria a seção 6.7.5.2 . 6.7.5.2 , parágrafo 4, que diz ( ênfase minha ):

Se o tamanho não estiver presente, o tipo de matriz é um tipo incompleto. Se o tamanho for * em vez de ser uma expressão, o tipo de matriz é um tipo de matriz de tamanho variável de tamanho não especificado, que só pode ser usado em declarações com escopo de protótipo de function; 124) tais matrizes são, no entanto, tipos completos. Se o tamanho for uma expressão constante inteira e o tipo de elemento tiver um tamanho constante conhecido, o tipo de matriz não é um tipo de matriz de comprimento variável; caso contrário, o tipo de matriz é um tipo de matriz de comprimento variável .