for compile c++ c++11 gcc clang language-lawyer

c++ - compile - llvm 3.7 1



¿Gcc o clang son correctos acerca de este comportamiento? (3)

Clang es correcto aquí. Primero , el alcance del parámetro de una función se define como:

Un parámetro de función (incluido uno que aparece en un declarador lambda) o una variable predefinida local de función ([dcl.fct.def]) tiene un alcance de parámetro de función. El alcance potencial de un parámetro o función-variable predefinida local comienza en su punto de declaración. [...]

y el punto de declaración se define como

El punto de declaración para un nombre es inmediatamente después de su declarador completo y antes de su inicializador (si lo hay), excepto como se indica a continuación. [Ejemplo:

unsigned char x = 12; { unsigned char x = x; }

Aquí el segundo x se inicializa con su propio valor (indeterminado). - ejemplo final]

Entonces, el value debe ser el value que acaba de declarar y no el del espacio global

Tengo un pequeño programa de juguetes:

static int value = 0; int function(int &value=value) { return value; } int main() { function(); }

Compilando con g ++ 7.2:

g ++ -std = c ++ 11 -Wall -Wextra test.cc -o test

No hay problema.

Compilando con clang ++ - 3.9:

clang ++ - 3.9 -std = c ++ 11 -Wall -Wextra test.cc -o test

test.cc:3:25: error: default argument references parameter ''value'' int function(int &value=value) { ^~~~~ test.cc:8:5: error: no matching function for call to ''function'' function(); ^~~~~~~~ test.cc:3:5: note: candidate function not viable: requires single argument ''value'', but no arguments were provided int function(int &value=value) { ^ 2 errors generated.

Kaboom. ¿Quién tiene la razón?


Creo que clang es correcto. Desde basic.scope.pdecl :

El punto de declaración para un nombre es inmediatamente después de su declarador completo (cláusula [dcl.decl] ) y antes de su inicializador (si lo hay), excepto como se indica a continuación. [Ejemplo:

int x = 12;{ int x = x; }

Aquí el segundo x se inicializa con su propio valor (indeterminado). - ejemplo final]

Además, desde dcl.fct.default :

Los argumentos predeterminados se evalúan cada vez que se llama a la función. El orden de evaluación de los argumentos de la función no está especificado. En consecuencia, los parámetros de una función no se utilizarán en un argumento predeterminado, incluso si no se evalúan. Los parámetros de una función declarada antes de un argumento predeterminado están dentro del alcance y pueden ocultar el espacio de nombres y los nombres de miembros de la clase


Dado que OP etiquetó la pregunta como c ++ 11, verifiqué esa versión del estándar y en la [basic.lookup.unqual] 11 de [basic.lookup.unqual] establece explícitamente que:

Durante la búsqueda de un nombre utilizado como argumento predeterminado (8.3.6) en una función parameter-declaration-clause o utilizado en la expresión de un mem-initializer para un constructor (12.6.2), los nombres de los parámetros de la función son visibles y ocultar los nombres de las entidades declaradas en los ámbitos del bloque, clase o espacio de nombres que contienen la declaración de la función.

Por lo tanto, clang es correcto.