¿Por qué no se puede deducir el tipo de retorno de main?


Como era de esperar, lo siguiente falla en C++11 porque ese lenguaje no tiene deducción de tipo de retorno para las funciones estándar de bog:

auto main()
{
   return 0;
}

Sin embargo, C++14 lo hace, por lo 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, prohibiendo la deducción de tipo de retorno para main? ¿O ambos compiladores no cumplen?

(Por si sirve de algo, nunca en realidad hacer esto. int main() para la victoria...)

Author: Lightness Races in Orbit, 2016-08-23

5 answers

Leyendo el borrador de C++17 §3.6.1/2:

... y tendrá un tipo de retorno declarado de type int, ...

Así que 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):

Tendrá un tipo de retorno declarado de type int,...


Solo una reflexión personal sobre el posible razonamiento detrás esto, después de leer comentarios y otras respuestas. El razonamiento deducción de tipo de retorno no está permitido es (creo) porque entonces el tipo de retorno no es conocido por el compilador hasta que ve una instrucción return. Tampoco es raro que se devuelvan otros tipos (que son implícitamente convertibles a int), lo que haría que el tipo deducido fuera incorrecto. Declarar el tipo de retorno por adelantado (ya sea de la manera tradicional normal, o usando el tipo de retorno final) establecerá el tipo cuando la función declarado, y puede ser comprobado por el compilador entonces y allí para ser correcto.

En cuanto a permitir alias de tipo, son simplemente alias de un tipo. Lo que permite, por ejemplo,

typedef int my_type;
my_type main() { ... }

No es realmente diferente de

int main() { ... }
 22
Author: Some programmer dude,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-24 04:30:01

De 3.6.1 / 2 (énfasis mío):

[...]tendrá un tipo de retorno declarado de tipo int, pero por lo demás su tipo está definido por la implementación.

Cuando auto se usa sin un tipo de retorno final, el tipo de retorno declarado de una función sigue siendo auto, a pesar de que 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 [...] una instrucción return se produce en una función declarada con un tipo de retorno 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 un return sin operando o con un operando de tipo void, el tipo de retorno declarado será auto y el tipo de retorno deducido será void.

Mi entendimiento es que con esto:{[15]]}

auto main(){ return 0; }

El declarado el tipo de retorno seguiría siendo auto, aunque el tipo de retorno deducido sería int. Según 3.6.1 / 2 anterior, el tipo de retorno declarado de main debe ser int. Por lo tanto, esto está mal formado.

Sin embargo, un tipo de retorno final se considera un tipo de retorno declarado . De 7.1.6.4 / 2:

Si el declarador de la función incluye un trailing-return-type (8.3.5), ese trailing-return-type especifica tipo de retorno declarado de la función.

$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$

Todas las comillas son idénticas tanto en C++14 como en C++17.

 17
Author: isanae,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-24 02:31:39

De 3.6.1 [básico.empezar.principal]

1 Un programa contendrá una función global llamada main, que es la inicio designado del programa....
2 Una aplicación no predefine la función principal. Esta función no se sobrecargará. Se tendrá un tipo de retorno declarado de tipo int, pero por lo demás su tipo se define la implementación...

Si el estándar restringiera la deducción, entonces creo que la verborrea "declared return type int" sería se.

 8
Author: AndyG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-23 17:03:53

Muchas respuestas mencionan muy bien las citas del estándar. Pero hay otro problema sutil con auto como tipo de retorno.

De acuerdo con el estándar C++ ( en algún lugar), el return la instrucción no es obligatoria dentro de main(). Esto se menciona explícitamente en el sitio web de Bjarne Stroustrup :

En C++, main() no necesita contener una instrucción return explícita. En ese caso, el valor devuelto es 0, lo que significa una ejecución exitosa.

Lo que significa que la siguiente declaración es válida:

auto main () {}

Uno puede asumir una sentencia implícita return 0; justo antes de }. Así que en tal caso auto es interpretado como int. Sin embargo, del tecnicismo de C++14, el auto debe ser deducido a void ¡porque no hay declaración de devolución! Entonces, " int vs void", ¿qué considerar?

IMO esta es la advertencia, que impide auto como un tipo de retorno en un sentido lógico también.

 4
Author: iammilind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:29:27

Como se discutió en varios comentarios, de hecho me faltaba en el estándar, porque lo que pensé que era una copia de la FDIS de C++14 no era de hecho tal cosa (sino, en cambio, un borrador ligeramente más antiguo), y la palabra "declarado" se coló en el pasaje relevante después de CWG 1669.

 3
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-23 17:11:41