No entiendo por qué esto compila


80

Ciertamente me falta algo, pero no entiendo por qué esto se compila (con g ++ y clang ++):

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

En primer lugar, Bes un tipo ... no un valor. ¿Cómo debo interpretar este código?


37
Esto se conoce como el Parse más
irritante

8
@alterigel ¿Es realmente? En este caso no hay ambigüedad. Solo puede ser una declaración de función. No es lo A a(B());que podría ser una definición variable o una declaración de función.
nogal

8
Te sorprendería saber que struct A{}; int main() { A(foo); } compila tal cual , incluso si foono nombra nada.
Ayxan

20
@alterigel: este no es el análisis más irritante. Mire los ejemplos en la página a la que se vinculó. Esto es simplemente una declaración de función.
Pete Becker

3
@PeteBecker, podría ser mejor explicar por qué esto no es MVP en lugar de simplemente afirmar que no lo es, lo que creo que Walnut ya hizo anteriormente.
JPhi1618

Respuestas:


84

Se interpreta como la declaración de una función denominada a, que toma un argumento de tipo By devuelve A.


55
Y es por eso que es Most y Vexing. Una solución: (no es que realmente resuelva nada ya que expone la mala construcción)A a{B};
user4581301

23
@ user4581301 - es no más de análisis del disgusto. Es simplemente una declaración de función.
Pete Becker

23
Entonces resulta que es solo un análisis sobre todo irritante ...
MooseBoys

11
La parte más extraña al respecto es que C ++ no permite funciones anidadas, pero permite declaraciones dentro de una función.
The_Sympathizer

66
Suena como una buena motivación para agregar soporte para funciones anidadas a C ++; no solo serían útiles, sino que convertirían esta extraña verruga en un diseño razonable :)
Jeremy Friesner

15

Es simplemente una declaración de función que declara aser una función que regresa Ay toma un parámetro de tipo sin nombre B.

Es válido porque las declaraciones de función en lugar de las definiciones de función están permitidas dentro de las definiciones de función.


13

Este problema se conoce como el análisis más irritante . La línea A a(B);se puede interpretar como la declaración de una función llamada que adevuelve un objeto de tipo Ay toma un parámetro de tipo sin nombre B.

Una forma de evitar este problema es usar la sintaxis de inicialización uniforme que se introdujo en C ++ 11, que consiste en usar llaves en lugar de paréntesis: A a{B};devuelve un error. La línea ahora se interpreta como una declaración de variable inicializada con B, que es un tipo en lugar de un valor.

Aquí hay más información:

El análisis más irritante: cómo detectarlo y solucionarlo rápidamente


12
No creo que esto deba llamarse " análisis más irritante ". Es solo una declaración de función habitual, ya que también existe en C. No es necesaria una resolución de ambigüedad porque la línea solo puede ser una declaración de función, nada más. Mira tu enlace. Los ejemplos son todos diferentes de esto.
nogal

3
Si bien eso es cierto, está relacionado con el análisis más irritante. Es solo que esto también incluía un error tipográfico donde un nombre de tipo se usaba solo en lugar de una variable o una llamada de constructor, como probablemente fue la intención original.
Miral

1
Sí, "Most Vexing Parse" es una respuesta útil en este caso, a pesar de que el caso real en la pregunta es solo "Slightly Vexing Parse".
jpa

1
@wlanut: las estructuras vacías struct A { };no son válidas en el estándar C, incluso si algunos compiladores lo permiten. Suelta los frenos y no habría problema allí. Además, en C, declarar o definir struct Ano crea un nombre de tipo A(debe structagregarle el prefijo o agregarlo en typedef struct A A;algún lugar antes de Ausarlo sin el structprefijo). También en C, no hay un análisis alternativo a la declaración de función: el uso type name(...);simplemente no puede ser una definición variable; siempre es una declaración de función (o no válida). El código en la pregunta no es válido en C.
Jonathan Leffler
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.