Pregunta

¿Alguien puede explicar por qué el siguiente código no se compila (en G ++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

El mensaje que recibo es:

jjj.cpp: en función 'int main ()':
jjj.cpp: 10: 'xx :: a' no es un miembro estático de 'struct x'
JJJ.CPP: 10: No hay función coincidente para llamar a 'x :: x ()'
jjj.cpp: 1: los candidatos son: x :: x (const x &)
jjj.cpp: 5: x :: x (x :: estado) `

¿Es este código malo o un error del compilador?

Problema resuelto por Neil+Konrad. Vea los comentarios a la respuesta de Neil a continuación.

¿Fue útil?

Solución

X(X::A);

está siendo visto como una declaración de función. Si realmente quieres este código, usa:

(X)(X::A);

Otros consejos

Has olvidado el nombre de la variable en tu definición:

int main()
{
   X my_x(X::A);
}

Su código confunde el compilador porque sintácticamente no puede distinguir esto de una declaración de función (regresar X y pasar X::A como argumento). En caso de duda, el compilador C ++ siempre desambigra a favor de una declaración.

La solución es introducir paréntesis redundantes alrededor del X Dado que el compilador prohíbe a los paréntesis alrededor de los tipos (en oposición a las llamadas de construcción, etc.):

(X(X::A));

Solo para que sea claro lo que sucede. Mira este ejemplo

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

¿Qué saldrá? Bueno, saldrá 0. los int(a) de arriba se puede analizar de dos maneras diferentes:

  • Echar int y descartar el resultado
  • Declarar una variable llamada a. Pero ignora los paréntesis alrededor del identificador.

El compilador, cuando tal situación aparece donde se usa un reparto de estilo funcional en una declaración y también parece una declaración, siempre la tomará como una declaración. Cuando no puede ser sintácticamente una declaración (el compilador mirará toda la línea para determinar eso), se considerará una expresión. Así estamos asignando al interior a arriba, dejando el exterior a a cero.

Ahora, tu caso es exactamente eso. Está intentando (accidentalmente) declarar un identificador llamado A Dentro de una clase llamado X:

X (X::A); // parsed as X X::A;

Luego, el compilador gime sobre un constructor predeterminado no declarado, porque la estática, como supone que es, está construida por defecto. Pero incluso si tuvo un constructor predeterminado para X, por supuesto todavía está equivocado porque ni A es un miembro estático de X, ni una estática de X puede definirse/declararse en el alcance del bloque.

Tu puedes hacerlo no Parece una declaración haciendo varias cosas. Primero, puedes analizar toda la expresión, lo que hace que ya no parezca una declaración. O simplemente paren el tipo que se lanza. Ambas desambiguaciones se han mencionado en otras respuestas:

(X(X::A)); (X)(X::A)

Hay una ambigüedad similar pero distinta cuando intentas declarar un objeto. Mira este ejemplo:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

Porque int(a) puede ser tanto la declaración de un parámetro llamado a y la conversión explícita (fundición) del flotador-variable a un int, el compilador decide nuevamente que esa es una declaración. Por lo tanto, declaramos una función llamada b, que toma un argumento entero y devuelve un entero. Existen varias posibilidades de cómo desambiguar eso, en función de la desambiguación de lo anterior:

int b((int(a))); int b((int)a);

Debes declarar un objeto como

X x(X::A);

Error en su código.

Cualquiera de estas dos líneas funcionan para mí:

X obj(X::A);
X obj2 = X(X::A);

Como señala Neil Butterworth, X(X::A) está siendo tratado como una declaración de función. Si realmente quieres un objeto anónimo, (X)(X::A) construirá un objeto X y lo eliminará inmediatamente.

Podrías, por supuesto, hacer algo como esto:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

Esto sería más legible y básicamente tendrá el mismo efecto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top