97 votes

En C++, si throw est une expression, quel est son type ?

J'ai trouvé ça lors d'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. C'est en fait assez clairement expliqué dans la norme C++, à la fois dans le texte principal et dans la grammaire. Cependant, ce qui n'est pas clair (pour moi du moins), c'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 vomi sur //2 parce que les types dans l'opérateur conditionnel sont différents. Ainsi, le type d'un throw L'expression ne semble pas être nulle.

Alors, qu'est-ce que c'est ?

Si vous répondez, veuillez étayer vos affirmations par des citations de la norme.


Il s'est avéré qu'il ne s'agissait pas tant du type d'une expression de rejet que de la façon dont l'opérateur conditionnel traite les expressions de rejet - quelque chose que je ne connaissais certainement pas avant aujourd'hui. avant aujourd'hui. Merci à tous ceux qui ont répondu, et en particulier à David Thornley.

82voto

David Thornley Points 39051

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 type throw (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 de type throw, mais utilisera simplement l'autre type.

En fait, l'article 15.1, paragraphe 1 dit explicitement "Une expression de type throw est de type void".

27voto

Draemon Points 15448

"Une expression de type throw est de type void"

ISO14882 Section 15

12voto

Marc Mutz - mmutz Points 10367

D'après [expr.cond.2] (opérateur conditionnel) ?: ) :

Si le deuxième ou le troisième opérande a le type (éventuellement cv-qualified) void, alors les conversions standard lvalue-to-rvalue, tableau à pointeur, et fonction à pointeur sont effectuées sur les deuxième et troisième opérandes et troisième opérande, et l'une des conditions suivantes doit être remplie :

- Le deuxième ou le troisième opérande (mais pas les deux) est une expression de type throw ; le résultat est du même type que l'autre et est une rvalue.

- Le deuxième et le troisième opérande sont de type void ; le résultat est de type void et est une rvalue. [Note : ceci inclut le cas où les deux opérandes sont des expressions de type throw. - note de fin ]

Ainsi, avec //1 vous étiez dans le premier cas, avec //2 vous avez enfreint la règle "l'une des conditions suivantes doit être remplie", car aucune d'entre elles ne l'est, dans ce cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X