2011-12-06 40 views
15

Un poco conocida, pero casi nunca se utiliza característica de C++ se da una declaración:función de sintaxis intento de captura y principal

void foo(); 

Una posible definición legal podría ser:

void foo() try { 
    throw 42; 
} 
catch(...) { 
} 

Aquí el whole function implementation wrapped is within a try/catch pair, que parece ser similar a permitir this.

¿Es eso legal hacer por int main()? Por ejemplo:

int main() try { 
    throw 42; 
} 
catch(...) { 
} 

The rules for main, n3290 § 3.6.1 sobre todo hablar de lo argumentos que debe tomar y lo que devuelve - que no parecen prohibir explícitamente como lo hacen con varias otras cosas extrañas (por ejemplo, vínculos) es posible que tengas la tentación de probar.

¿Es esto legal y bien definido?

+2

Pregunta académica interesante, aunque no estoy seguro de que tenga un uso muy práctico. http://stackoverflow.com/a/620817/10077 –

+0

¿Legal? Técnicamente, la mayoría de los compiladores lo soportarán. Bien definido? No realmente, ya que ciertamente no puedo pensar en ninguna razón sensata para hacer esto. – AJG85

+0

@ AJG85 - Quise decir bien definido en el sentido de "invocación de comportamiento indefinido, ni comportamiento definido de implementación", no en el modo "bien probado en implementaciones comunes" – Flexo

Respuesta

7

La norma no prohíbe su uso dentro [basic.start.main], y, mientras que obliga a todas las implementaciones de apoyo al menos int main() {/*...*/ } y int main(int argc, char* argv[]) {/*...*/}, no limita las implementaciones a esas dos declaraciones (3.6.1, párrafo 2).

De forma aislada, parecería al menos que es legal, aunque, por supuesto, se refiere solo a las declaraciones de funciones, no a las definiciones de funciones.

Lectura en, [except.handle], párrafo 13 indica lo siguiente:

Excepciones lanzadas en los destructores de objetos con almacenamiento estático duración o en los constructores de objetos de espacio de nombres de alcance no son capturados por un function-try-block en main(). (. 15.3 párrafo 13)

Se hace mención específica de un función-TRY-bloque colocado en main(), lo que implica fuertemente que tal estructura es legal y ha definido comportamiento. Agregar la información de que main() es solo especial en su nombre y tipo de retorno, y que las implementaciones no pueden sobrecargarlo para alterar cualquier comportamiento, hace un caso bastante sólido de que actúa de manera normal excepto cuando se lo menciona especialmente como en la cita anterior . En otras palabras, sí, es legal y está bien definido.

La entrada de blog que suministré en la primera versión de esta respuesta realmente hace un buen trabajo de ilustrar las reglas dadas por el blockquote arriba, así que voy a retain the link to it, a pesar de que no trata directamente el tema en el PO de pregunta.

En cuanto a un comentario sobre el OP, puede emitir declaraciones de devolución dentro de un function-try-block, y [excepto.handle] tiene esto que decir:

Salir del final de una función-try-block es equivalente a un retorno sin valor; esto da como resultado un comportamiento indefinido en una función de devolución de valor (6.6.3). (15.3 párr. 15)

Si estás en un bloque catch al final de main, usted no va a fluir sobre el cuerpo de la función (que sería el intento de bloque en este caso) , por lo que no se aplica la regla de que main llama automáticamente a return 0; en flowover. Debe devolver algún int (muy posiblemente un código de error) para evitar volverse indefinido.

+1

No hay mucha información (sobre la definición), las constataciones 'estáticas 'son bastante simples: los objetos" globales "se inicializan antes de que se llame y se destruya' main' después de que ha regresado ... así que obviamente no está dentro del 'try/catch' bloquear. En cuanto a las observaciones sobre la sintaxis del constructor, sí, es extraño, pero en realidad tampoco responde la pregunta ... –

+0

Estoy de acuerdo con esa evaluación y la he tomado nota; Gracias. Encontré una referencia explícita a 'main()' que tiene function-try-blocks, así que creo que el artículo es bastante inútil de todos modos. Haré una edición para aclarar esto. – matthias

+0

Esa cita de 15.3 es bastante interesante.(Esa sería posiblemente mi próxima pregunta si fuera legal) Combinada con la DR a la que Johannes se vinculó parece responderla según lo permitido. – Flexo

0

Lo he probado, compila y funciona como se esperaba. Una formulación peculiar, pero no creo que rompa ninguna regla. Para mayor claridad (por sí mismo y futuros quienes mantienen código), también se puede reformular como:

int main() 
{ 
    try { 
     throw 42; 
    } 
    catch(int /*...*/) { 
    } 
} 
+4

Funciona en mi compilador también. El problema con "compila y ejecuta" es que sé que mi compilador compila y ejecuta muchas cosas que no están bien definidas. – Flexo

+1

Punto justo, @awoodland. Entonces, en la duda, sugeriría usar la formulación que mencioné arriba, que parece hacer exactamente lo que usted requiere. Sin embargo, su formulación original no parece romper ninguna regla del estándar. – alexandreC

Cuestiones relacionadas