c++ - ejemplo - auto en c
¿Por qué no se puede deducir el tipo de retorno de main? (5)
Como se discutió en varios comentarios, realmente me faltaba en el estándar, porque lo que pensé que era una copia del C ++ 14 FDIS en realidad no era tal cosa (pero, en cambio, un borrador marginalmente más antiguo), y la palabra " declaró que "se coló en el pasaje relevante después del CWG 1669" .
Como se esperaba, lo siguiente falla en C ++ 11 porque ese lenguaje no tiene deducción de tipo de retorno para las funciones estándar de pantano:
auto main()
{
return 0;
}
Sin embargo, C ++ 14 sí lo hace, así que no puedo explicar el siguiente error (con resultados equivalentes en GCC trunk, clang 3.8 y Visual Studio 2015):
error: ''main'' must return ''int''
¿Hay un pasaje en el estándar que no estoy viendo, que prohíbe la deducción del tipo de devolución para main
? ¿O ambos compiladores no son compatibles?
(Por lo que vale, nunca haría esto. int main()
por la victoria ...)
De 3.6.1 / 2 (énfasis mío):
[...] tendrá un tipo de retorno declarado de tipo
int
, pero de lo contrario su tipo está definido por la implementación.
Cuando se usa auto
sin un tipo de retorno final, el tipo de devolución declarado de una función sigue siendo auto
, aunque el tipo de retorno deducido puede ser otra cosa. La diferencia entre declarado y deducido no se explica claramente en el estándar, pero 7.1.6.4/7 puede arrojar algo de luz:
Cuando se produce una declaración de
return
en una función declarada con un tipo de devolución que contiene un tipo de marcador de posición, el tipo de [...] retorno deducido se determina a partir del tipo de su inicializador. En el caso de unreturn
sin operando o con un operando de tipovoid
, el tipo de retorno declarado seráauto
y el tipo de retorno deducido serávoid
.
Mi entendimiento es que con esto:
auto main(){ return 0; }
el tipo de retorno declarado aún sería auto
, aunque el tipo de retorno deducido sería int
. Según 3.6.1 / 2 arriba, el tipo de retorno declarado de main
debe ser int
. Por lo tanto, esto está mal formado.
Sin embargo, un tipo de devolución final se considera un tipo de devolución declarada . Desde 7.1.6.4/2:
Si el declarador de función incluye un tipo de retorno final (8.3.5), ese tipo de retorno final especifica el tipo de retorno declarado de la función.
$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$
Todas las citas son idénticas tanto en C ++ 14 como en C ++ 17.
Desde 3.6.1 [basic.start.main]
1 Un programa debe contener una función global llamada main, que es el inicio designado del programa ....
2 Una implementación no debe predefinir la función principal. Esta función no debe estar sobrecargada. Deberá tener un tipo de devolución declarada de tipo int, pero de lo contrario su tipo está definido por la implementación ...
Si el estándar fuera restringir la deducción, entonces creo que la verborrea "declarada return type int" sería esa.
Leyendo el borrador de C ++ 17 §3.6.1 / 2:
... y tendrá un tipo de devolución declarada de tipo
int
, ...
Entonces sí, diría que está prohibido usar la deducción.
Casi la misma redacción en el último borrador de C ++ 14 (misma sección que el borrador de C ++ 17):
Deberá tener un tipo de devolución declarada de tipo
int
, ...
Solo una reflexión personal sobre el posible razonamiento detrás de esto, después de leer comentarios y otras respuestas. La deducción por tipo de devolución de razonamiento no está permitida (creo) porque el compilador no conoce el tipo de devolución hasta que ve una declaración de return
. Tampoco es raro que otros tipos (que son implícitamente convertibles a int
) puedan ser devueltos, lo que haría que el tipo deducido sea incorrecto. Declarar el tipo de devolución por adelantado (ya sea a la manera tradicional pasada de moda o utilizando el tipo de devolución final) establecerá el tipo cuando se declare la función, y el compilador puede verificarlo en ese momento para asegurarse de que sea correcto.
En cuanto a permitir alias de tipo, son solo alias de un tipo. Entonces, por ejemplo, permitiendo
typedef int my_type;
my_type main() { ... }
realmente no es diferente de
int main() { ... }
Muchas respuestas han mencionado muy bien las citas del estándar. Pero hay otro problema sutil con el auto
como tipo de devolución.
Según el estándar de C ++ (en somewhere ), la declaración de return
no es obligatoria dentro de main()
. Esto se menciona explícitamente en el website Bjarne Stroustrup:
En C ++,
main()
no necesita contener una declaración dereturn
explícita. En ese caso, el valor devuelto es0
, lo que significa ejecución exitosa.
Lo que significa que la declaración a continuación es válida:
auto main () {}
Uno puede asumir un return 0;
implícito return 0;
declaración justo antes }
. Entonces, en tal caso, auto
se interpreta como int
. Sin embargo, a partir del tecnicismo de C ++ 14, el auto
debe deducirse como void
porque no hay declaración de devolución. Entonces, " int
vs void
", ¿qué considerar?
OMI esta es la advertencia, que también evita el auto
como un tipo de retorno en un sentido lógico.