gct
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 -Muro -Wextra prueba.cc -o prueba
No hay problema.
Compilando con clang++-3.9:
clang++-3.9 -std=c++11 -Wall -Wextra test.cc -o prueba
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.
Kabum. ¿Quién tiene razón?
R Sahú
Creo que clang es correcto. De basic.scope.pdecl:
El punto de declaración de 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. [ Example:
int x = 12;{ int x = x; }
Here the second x is initialized with its own (indeterminate) value. — end example ]
También, 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 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 los miembros de la clase.
-
Esa parece ser la respuesta, sorprendido de que gcc se lo haya perdido.
– gct
13 de febrero de 2018 a las 16:57
-
@SeanMcAllister, sí, es sorprendente que g ++ se pierda este.
– R Sahu
13 de febrero de 2018 a las 16:58
-
Pero esta cita no prohíbe que el argumento predeterminado haga referencia al parámetro de función como se queja de clang.
– usuario7860670
13 de febrero de 2018 a las 17:00
-
-
El único caso de uso sería tomar la dirección del parámetro para definir su propio valor. ¿Quién lo hizo? ¿Por qué exponer al codificador a errores para un caso tan inútil? El estándar es incorrecto, por lo que gcc tiene razón al estar equivocado.
– oliva
13 de febrero de 2018 a las 20:54
johan
Dado que el OP etiquetó la pregunta como c ++ 11, verifiqué esa versión del estándar y en [basic.lookup.unqual] la subcláusula 11 establece explícitamente que:
Durante la búsqueda de un nombre utilizado como argumento predeterminado (8.3.6) en una cláusula de declaración de parámetro de función o utilizado en la expresión de un inicializador de mem para un constructor (12.6.2), los nombres de los parámetros de función son visibles y ocultar los nombres de las entidades declaradas en los ámbitos de bloque, clase o espacio de nombres que contienen la declaración de la función.
Por lo tanto, clang es correcto.
NathanOliver
Clang es correcto aquí. Primero un alcance del parámetro de la 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 ámbito de parámetro de función. El alcance potencial de una variable predefinida local de función o parámetro comienza en su punto de declaración.[…]
y el punto de declaración Se define como
El punto de declaración de 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. [ Example:
unsigned char x = 12; { unsigned char x = x; }
Here the second x is initialized with its own (indeterminate) value. — end example ]
Asi que value
debería ser el value
acabas de declarar y no el del espacio global
int function(int &value=value)
me parece muy raro. cambiaría eso porint function(int &value = ::value)
por lo que se refiere al mundovalue
en lugar de que la referencia esté ligada a sí misma.– Eljay
13 de febrero de 2018 a las 16:45
@Eljay
gcc
lo une a lo globalvalue
conint& value = value
pero creo que está mal según el estándar actual.– Holt
13 de febrero de 2018 a las 16:46
solo curiosidad: cuando ejecuta el gcc, ¿cuál es el valor del valor local? (ohh dios, esa pregunta ha salido mal)…
– Mono del Reino Unido
13 de febrero de 2018 a las 16:46
A juzgar por el hecho de que puedes usar
decltype(param)
en el argumento predeterminado, diría que el nombre del parámetro está dentro del alcance y GCC es incorrecto, pero esa no es una base muy sólida.– chris
13 de febrero de 2018 a las 16:49
@UKMonkey Aparentemente es el valor real de
::value
es decir, la referencia no se vincula a sí misma.– Quintín
13 de febrero de 2018 a las 16:50