2016-07-11 72 views
5

Il sito di http://en.cppreference.com/w/cpp/language/fold dà un esempio di come utilizzare il concetto piega, e dice:C++ 17: cosa significa "operatore con precedenza sotto cast" nel concetto di "piega"?

Come non madrelingua inglese, non smettere di prendere la frase:

has an operator with precedence below cast at the top level 

Che cosa significa in realtà, e l'esempio, cosa indica? Potrebbe aiutarmi a spiegare questo?

Grazie mille.

+3

Significa nulla al di sotto la linea 3 della [tabella delle precedenze] (http://en.cppreference.com/w/cpp/language/operator_precedence). –

risposta

7

L'operatore di casting ((Typename)expr) ha una precedenza molto elevata in C++'s operator precedence rules. Pochissimi operatori hanno una precedenza più alta di quella. Gli operatori con livello di cast o precedenza maggiore sono operazioni molto speciali, che di solito si applicano a una singola espressione.

Nell'espressione args + ... + 1 * 2, lo ... si applica a tutto sia a sinistra che a destra. Ma cosa significa "a destra"? Significa solo la parte + 1 o significa + 1 * 2?

Nel caso di operatori con precedenza elevata, è chiaro quale sia l'intento. Ad esempio, args + ... + func(), è chiaro che l'operatore di chiamata della funzione () si applica a func e non a args + ... + func. È così improbabile che tu voglia che quest'ultimo sia obbligato a usare le parentesi in modo esplicito se lo hai fatto ((args + ... + func)()).

Tuttavia, per i livelli di precedenza inferiori a 3 nel grafico, le cose diventano molto più torbide per le persone da comprendere. Quindi, invece di usare le normali regole di precedenza, C++ costringe l'utente ad esserne esplicito. È possibile avere args + ... + (1 * 2) o (args + ... + 1) * 2. Ma devi essere chiaro quale vuoi.

+0

La tua spiegazione è chiara per me. –

+1

Poiché le espressioni di piega sono '(exp1 op ... op exp2)' con i paren, dubito che ci sia un'ambiguità di parsing effettiva. Probabilmente è lì in modo che sia chiaro agli umani, non solo ai compilatori. –

1

Significa che se un'espressione con più operatori è ambigua, gli operatori che sono "sopra il cast" verranno chiamati prima dell'operatore di cast e gli operatori "sotto il cast" verranno chiamati dopo l'operatore di cast. Come in 2 + 2 * 2 moltiplicazione deve essere eseguito prima dell'aggiunta, con conseguente 6, ma non 8.

Consideriamo i seguenti due classi che sono calcinabile tra loro:

class E2; 

class E1 { 
public: 

    operator E2(); 

    E1 operator++(int) { 
    std::cout << "E1 Post-inc\n"; 
    return *this; 
    } 

    E1 operator*(const E1&) { 
    std::cout << "E1 * E1\n"; 
    return *this; 
    } 
}; 

class E2 { 
public: 

    operator E1() { 
    std::cout << "Cast E1 -> E2\n"; 
    return E1(); 
    } 

    E2 operator++(int) { 
    std::cout << "E2 Post-inc\n"; 
    return *this; 
    } 

    E2 operator*(const E2&) { 
    std::cout << "E2 * E2\n"; 
    return *this; 
    } 
}; 

E1::operator E2() { 
    std::cout << "Cast E2 -> E1\n"; 
    return E2(); 
} 

Poi dichiariamo

E1 e1; 
E2 e2; 

e fare

Sia E1 che E2 hanno funzionato oppure ++, quindi cosa deve essere fatto prima in questa espressione: cast o incremento? Precedence table risposte che incrementano dovrebbe essere fatto prima, in modo che il programma stampa

E2 Post-inc 
Cast E1 -> E2 

Allora, proviamo un esempio più complicato:

e1 * (E1)e2++; 

Qui abbiamo 3 azioni (in ordine di apparizione in codice) : moltiplicazione, cast e incremento. Che ordine hai se l'esecuzione sarà?La tabella di precedenza dice che l'incremento è il primo, il cast è il secondo (è inferiore all'incremento) e la moltiplicazione è l'ultima, poiché è al di sotto di entrambi. Quindi l'output sarà:

E2 Post-inc 
Cast E1 -> E2 
E1 * E1 

Si noti che è possibile riordinare facilmente le operazioni utilizzando le parentesi. Ad esempio, se sostituiamo e1 * (E1)e2++; con (e1 * (E1)e2)++;, ci arriveremo

Cast E1 -> E2 
E1 * E1 
E1 Post-inc 
+0

Buona risposta, grazie! –