c++ throw

c++ - throw c#



En C++, si throw es una expresión, ¿cuál es su tipo? (4)

Recogí esto en una de mis breves incursiones para reddit:

http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/

Básicamente, el autor señala que en C ++:

throw "error"

es una expresion. Esto está de hecho bastante claro en el Estándar C ++, tanto en el texto principal como en la gramática. Sin embargo, lo que no está claro (al menos para mí) es ¿cuál es el tipo de expresión? Adiviné " void ", pero un poco de experimentación con g ++ 4.4.0 y Comeau dieron como resultado este código:

void f() { } struct S {}; int main() { int x = 1; const char * p1 = x == 1 ? "foo" : throw S(); // 1 const char * p2 = x == 1 ? "foo" : f(); // 2 }

Los compiladores no tuvieron problemas con // 1, pero abrieron en // 2 porque los tipos en el operador condicional son diferentes. Entonces, el tipo de expresión de throw no parece ser nulo.

¿Así que qué es lo?

Si responde, haga una copia de seguridad de sus declaraciones con citas del Estándar.

Resultó que no se trataba tanto del tipo de expresión de un lanzamiento como de cómo el operador condicional trata las expresiones de lanzamiento, algo que ciertamente no sabía antes de hoy. Gracias a todos los que respondieron, pero particularmente a David Thornley.


"Una expresión de lanzamiento es de tipo vacío"

ISO14882 Sección 15


Desde [expr.cond.2] ( ?: operador condicional ?: :):

Si el segundo o el tercer operando tienen un tipo (posiblemente cv-quali fi cado) void, entonces las conversiones estándar de lvalue-a-rvalue, de matriz a puntero y de función a puntero se realizan en el segundo y tercer operandos, y uno de los siguientes debe contener:

- El segundo o el tercer operando (pero no ambos) es una expresión de lanzamiento; el resultado es del tipo del otro y es un valor r.

- Tanto el segundo como el tercer operandos tienen tipo vacío; el resultado es de tipo vacío y es un valor r. [Nota: esto incluye el caso donde ambos operandos son expresiones de lanzamiento. - nota final]

Entonces, con //1 estaba en el primer caso, con //2 , estaba violando "se mantendrá uno de los siguientes", ya que ninguno de ellos lo hace, en ese caso.


Puede hacer que una impresora de tipo lo escuche por usted :

template<typename T> struct PrintType; int main() { PrintType<decltype(throw "error")> a; }

Básicamente, la falta de implementación de PrintType hará que el informe de error de compilación diga:

instanciación implícita de plantilla indefinida PrintType<void>

así que podemos verificar que las expresiones de throw son de tipo void (y sí, las cotizaciones estándar mencionadas en otras respuestas verifican que este no es un resultado específico de la implementación, aunque gcc tiene dificultades para imprimir información valiosa)


Según el estándar, 5.16 párrafo 2 primer punto, "El segundo o el tercer operando (pero no ambos) es una expresión de lanzamiento (15.1); el resultado es del tipo del otro y es un valor r". Por lo tanto, al operador condicional no le importa qué tipo es una expresión de lanzamiento, sino que solo usará el otro tipo.

De hecho, 15.1, párrafo 1 dice explícitamente "Una expresión de lanzamiento es de tipo vacío".