c++ - para - ¿Por qué esta enumeración no se convierte a int?
struct c++ (3)
¿Por qué el siguiente código no se compila bajo g ++ (C ++ 14), MSVC (C ++ 14) o ARM (C ++ 03)?
La instancia de error denominada llama al constructor de enteros, pero la instancia de error anónima no se resuelve.
class Error
{
public:
Error(int err) : code_(err) {}
const int code_;
};
enum Value
{
value_1
};
int main()
{
// compiles
Error e(value_1);
// does not compile under G++, ARM, or MSVC
Error(value_1);
}
Ejemplo de error en G ++: ( enlace Coliru )
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function ''int main()'':
main.cpp:19:18: error: no matching function for call to ''Error::Error()''
Error(value_1);
^
main.cpp:4:5: note: candidate: Error::Error(int)
Error(int err) : code_(err) {}
^~~~~
main.cpp:4:5: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(const Error&)
class Error
^~~~~
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(Error&&)
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
main.cpp: 19: 18: error: no hay función coincidente para la llamada a ''Error :: Error ()''
Error (value_1);
El compilador intenta llamar al constructor predeterminado inexistente Error::Error()
porque ve
Error(value_1);
como declaración de variable
Error value_1;
Se permite que una declaración tenga paréntesis redundante.
El problema es que el código
Error(value_1);
Es una declaración de una variable value_1
de tipo Error
.
Este es un legado del lenguaje C que usa expresiones como parte de una declaración de tipo.
Por ejemplo, int *i
es un puntero a int
porque dice que la expresión *i
debería evaluar para escribir int
. Más ejemplos de esto:
-
int (*func)()
es un puntero a la función que devuelveint
porque la expresión(*func)()
evalúa para escribirint
. -
int *p[8]
es una matriz de punteros aint
porque la expresión*p[x]
evalúa para escribirint
. -
int (*p)[8]
es un puntero a la matriz de 8int
''s (int[8]
) porque la expresión(*p)[x]
evalúa para escribirint
. -
int (*(*p[8])())()
es una matriz de 8 punteros a funciones que devuelven punteros a una función que devuelveint
porque la expresión(*(*p[x])())()
evalúa para escribirint
.
Similarmente, int (i)
es una variable simple de tipo int
cuando la expresión (i)
evalúa para escribir int
.
Y así, como C ++ hereda esto de C, usa paréntesis como parte de la declaración de tipo, pero también agrega más sintaxis en la parte superior, lo que lleva a algunos resultados inesperados.
La regla aplicada por C ++ aquí dice que tratar todo lo que puede ser una declaración como una declaración.
Confusión similar si a menudo es causada por un código como este:
Error ec();
que es una declaración directa de una función ec
que devuelve Error
.
Esto viene del mismo lugar que "The Most Vexing Parse": la regla de que si puede ser una declaración, es una declaración.
Y, sorprendentemente, se le permite poner paréntesis alrededor del identificador en una declaración de variable.
(No tengo idea de por qué, pero supongo que simplificó el analizador de C en el pasado).
Las siguientes son todas las declaraciones válidas de variables int
:
int (foo);
int (bar) = 0;
int (baz)(3);
int (twaddle)(baz);