Domanda

L'ho raccolto in una delle mie brevi incursioni su reddit:

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

Fondamentalmente, l'autore sottolinea che in C ++:

throw "error"

è un'espressione. Questo è in realtà abbastanza chiaramente enunciato nello standard C ++, sia nel testo principale che nella grammatica. Tuttavia, ciò che non è chiaro (almeno per me) è qual è il tipo di espressione? Ho indovinato " void " ;, ma un po 'di sperimentazione con g ++ 4.4.0 e Comeau ha prodotto questo codice:

    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
    }

I compilatori non hanno avuto problemi con // 1 ma sono stati scambiati su // 2 perché i tipi nell'operatore condizionale sono diversi. Quindi il tipo di espressione lancio non sembra essere nullo.

Quindi cos'è?

Se rispondi, esegui il backup delle dichiarazioni con citazioni dalla norma.


Ciò si è rivelato non tanto legato al tipo di espressione di lancio quanto al modo in cui l'operatore condizionale si occupa delle espressioni di lancio - qualcosa che certamente non ho sapere prima di oggi. Grazie a tutti coloro che hanno risposto, ma in particolare a David Thornley.

È stato utile?

Soluzione

Secondo lo standard, 5.16 paragrafo 2, primo punto, "Il secondo o il terzo operando (ma non entrambi) è un'espressione di lancio (15.1); il risultato è del tipo dell'altro ed è un valore. " Pertanto, l'operatore condizionale non si preoccupa del tipo di espressione di lancio, ma utilizzerà semplicemente l'altro tipo.

In effetti, 15.1, il paragrafo 1 dice esplicitamente "un'espressione di lancio è di tipo vuoto."

Altri suggerimenti

  

" Un'espressione di lancio è di tipo void "

ISO14882 Sezione 15

Da [expr.cond.2] (operatore condizionale ?: ):

  

Se il secondo o il terzo operando hanno il tipo (possibilmente cv-quali & # 64257; ed) vuoto, quindi il valore da lvalue a rvalue,   le conversioni standard da array a puntatore e da funzione a puntatore vengono eseguite sul secondo e   terzi operandi e uno dei seguenti deve contenere:

     

& # 8212; Il secondo o il terzo operando (ma non entrambi) è un'espressione di lancio;     il risultato è del tipo dell'altro ed è un valore.

     

& # 8212; Sia il secondo che il terzo operando hanno il tipo vuoto;     il risultato è di tipo vuoto ed è un valore.     [Nota: questo include il caso in cui entrambi gli operandi sono espressioni di lancio. & # 8212; nota finale]

Quindi, con // 1 eri nel primo caso, con // 2 , stavi violando "una delle seguenti considerazioni" poiché nessuna di loro, in quel caso.

Puoi avere una stampante di tipo sputartela per te :

template<typename T>
struct PrintType;

int main()
{
    PrintType<decltype(throw "error")> a; 
}

Fondamentalmente la mancanza di implementazione per PrintType provocherà la segnalazione dell'errore di compilazione:

  

istanziazione implicita di modello non definito PrintType<void>

in modo da poter effettivamente verificare che le espressioni throw siano di tipo void (e sì, le virgolette Standard citate in altre risposte verificano che questo non sia un risultato specifico dell'implementazione - sebbene gcc abbia difficoltà a stampare informazioni preziose)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top