c++ - El análisis más irritante
most-vexing-parse (2)
¿
int(x)
es esta sintaxisint(x)
en la declaraciónFoo f( int(x) );
¿medio?
Los paréntesis alrededor de
x
son superfluos y serán ignorados.
Entonces
int(x)
es igual a
int x
aquí, significa un parámetro llamado
x
con tipo
int
.
¿Es lo mismo que
Foo f( int x );
?
Sí.
Foo f( int(x) );
, es una declaración de función que se llama
f
, devuelve
Foo
, toma un parámetro llamado
x
con tipo
int
.
Aquí está la explicación del estándar. $ 8.2 / 1 Resolución de ambigüedad [dcl.ambig.res] :
(énfasis mío)
La ambigüedad que surge de la similitud entre un elenco de estilo de función y una declaración mencionada en [stmt.ambig] también puede ocurrir en el contexto de una declaración. En ese contexto, la elección es entre una declaración de función con un conjunto redundante de paréntesis alrededor de un nombre de parámetro y una declaración de objeto con una conversión de estilo de función como inicializador. Al igual que para las ambigüedades mencionadas en [stmt.ambig], la resolución es considerar cualquier construcción que pueda ser una declaración, una declaración . [Nota: Una declaración puede ser desambiguada explícitamente agregando paréntesis alrededor del argumento. La ambigüedad se puede evitar mediante el uso de la sintaxis de inicialización de copia o de inicialización de lista, o mediante el uso de una conversión sin estilo de función. - nota final] [Ejemplo:
struct S { S(int); }; void foo(double a) { S w(int(a)); // function declaration S x(int()); // function declaration S y((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration }
- ejemplo final]
Por lo tanto,
int(x)
se considerará como una declaración (de parámetro) en lugar de una conversión de estilo de función.
Esta pregunta ya tiene una respuesta aquí:
- Un detalle confuso sobre las respuestas más molestas de Parse 4
Vi un código aquí en Cpp Quiz [Pregunta # 38]
#include <iostream>
struct Foo
{
Foo(int d) : x(d) {}
int x;
};
int main()
{
double x = 3.14;
Foo f( int(x) );
std::cout << f.x << std::endl;
return 0;
}
Allí se dice que este código está mal formado porque
Foo f( int(x) );
se tratará como una declaración de función en lugar de una declaración de objeto de tipo
Foo
.
Hasta donde yo sé, esta es una instancia de la mayoría de los análisis molestos.
Mi pregunta es cuál es esta sintaxis
int (x)
en la declaración
Foo f( int(x) );
¿medio?
Hasta ahora solo vi declaraciones de funciones como:
-
Foo f( int );
y -
Foo f( int x );
¿Es lo mismo que
Foo f( int x );
?
El problema es que, por razones desconocidas para mí, es válido incluir los nombres de los parámetros entre paréntesis en los prototipos. Asi que
Foo f(int(x));
puede ser interpretado como
Foo f(int x);
eso se considera como
Foo f(int);
Sin embargo, el verdadero problema es que los autores de C ++, también por razones desconocidas para mí, decidieron que era genial tener dos formas de sintaxis diferentes para la misma semántica (inicialización de instancia).
Esto introduce una ambigüedad de sintaxis que se "resuelve" diciendo que "si algo puede ser tanto una declaración como una definición, entonces es una declaración", desencadenando la trampa.
Por eso, un analizador de C ++ debe poder analizar un número arbitrariamente grande de tokens antes de poder decidir cuál es el significado semántico del primero de ellos.
Aparentemente, esto no habría sido un gran problema, excepto para los escritores de compiladores, pero sin embargo, significa que también quien lea el código C ++ para comprenderlo debe ser capaz de hacer lo mismo, y para nosotros los humanos esto es más difícil. De eso el "más irritante".