J'ai ramassé ceci dans l'une de mes brèves incursions sur reddit:
http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/
En gros, l'auteur souligne qu'en C ++:
throw "error"
est une expression. Ceci est en fait assez clairement défini dans le standard C ++, à la fois dans le texte principal et dans la grammaire. Cependant, ce qui n'est pas clair (du moins pour moi), c'est quel est le type de l'expression? J'ai deviné " void
", mais un peu d'expérimentation avec g ++ 4.4.0 et Comeau a donné ce code:
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
}
Les compilateurs n'ont eu aucun problème avec // 1 mais ont barfié // 2 parce que les types dans l'opérateur conditionnel sont différents. Le type d' throw
expression ne semble donc pas nul.
Alors c'est quoi?
Si vous répondez, veuillez sauvegarder vos déclarations avec des citations de la norme.
Il s'est avéré que cela ne concernait pas tant le type d'une expression throw que la façon dont l'opérateur conditionnel traite les expressions throw - quelque chose que je ne savais certainement pas avant aujourd'hui. Merci à tous ceux qui ont répondu, mais particulièrement à David Thornley.
Réponses:
Selon la norme, 5.16 paragraphe 2 premier point, "Le deuxième ou le troisième opérande (mais pas les deux) est une expression de jet (15.1); le résultat est du type de l'autre et est une rvalue." Par conséquent, l'opérateur conditionnel ne se soucie pas du type d'une expression throw, mais utilisera simplement l'autre type.
En fait, 15.1, le paragraphe 1 dit explicitement "Une expression de jet est de type void."
la source
ISO14882, section 15
la source
void
De [expr.cond.2] (opérateur conditionnel
?:
):Donc, avec
//1
vous étiez dans le premier cas, avec//2
, vous violiez "l'un des éléments suivants tiendra", car aucun d'entre eux ne le fait, dans ce cas.la source
Vous pouvez demander à une imprimante de type de le recracher pour vous :
Fondamentalement, le manque d'implémentation de
PrintType
fera dire au rapport d'erreur de compilation:nous pouvons donc vérifier que les
throw
expressions sont de typevoid
(et oui, les guillemets standard mentionnés dans d'autres réponses vérifient qu'il ne s'agit pas d'un résultat spécifique à l'implémentation - bien que gcc ait du mal à imprimer des informations précieuses)la source