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.