type para libreria example enum c++ enums

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 devuelve int porque la expresión (*func)() evalúa para escribir int .
  • int *p[8] es una matriz de punteros a int porque la expresión *p[x] evalúa para escribir int .
  • int (*p)[8] es un puntero a la matriz de 8 int ''s ( int[8] ) porque la expresión (*p)[x] evalúa para escribir int .
  • int (*(*p[8])())() es una matriz de 8 punteros a funciones que devuelven punteros a una función que devuelve int porque la expresión (*(*p[x])())() evalúa para escribir int .

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);