2014-11-11 9 views
11

Ecco quello che stiamo cercando di faretry {....} catch (..) solo se una certa espressione fase di compilazione è vero

try { 
    std::uninitialized_copy(...); 
} catch(...) { 
    if(!boost::has_trivial_destructor<T>::value) { 
     // some cleanup to do here... 
    } 
    throw; 
} 

ci chiediamo se il try/catch ha un costo, se la costante di tempo di compilazione nello if è falsa.

È possibile che il compilatore con i propri diritti "as-if" rimuova il tentativo e si comporti come se la chiamata std::uninitialized_copy fosse visualizzata senza try attorno ad esso?

Oppure c'è qualcosa nascosto nelle specifiche C++ che richiede al compilatore di lasciarlo qui? Ad esempio, immagina un'ipotetica funzione surrounding_try_blocks() che restituisce il conteggio dei blocchi di prova dinamici che circondano attualmente attorno a un fotogramma.

+0

La prego di elaborare la vostra question.Like quando dici "fa try/catch ha un costo ... ". Che costo intendevi? Il solo mettere i blocchi try/catch ha un certo costo in termini di prestazioni – ravi

+0

Se ho capito la domanda, è: if 'boost :: ...'è vero quindi il codice potrebbe essere ottimizzato fino alla semplice chiamata a' unitialized_copy' dato che tutto ciò che cattura fa un'eccezione e poi la lancia di nuovo. Ma un compilatore è autorizzato a fare questa ottimizzazione? – Tommy

+0

se il compilatore ottimizza la dichiarazione if il tuo programma funziona esattamente come farebbe senza i blocchi try/catch, no? Quindi, non vedo quale sovraccarico ci sarebbe rimasto per il compilatore da ottimizzare. –

risposta

0

Di seguito sono riepilogati i costi dell'utilizzo dell'eccezione che ho raccolto da varie fonti. Come quello che chiedi nel tuo secondo punto non mi è molto chiaro. Quindi ho pensato fosse meglio attraversare tutto a te. Spero che tu scelga qualcosa della tua importanza.

Per gestire le eccezioni in fase di esecuzione, i programmi devono eseguire una buona quantità di contabilità. In ogni punto durante l'esecuzione di , devono essere in grado di identificare gli oggetti che richiedono la distruzione se viene lanciata un'eccezione; devono prendere nota di ogni entrata e uscita da un blocco try; e per ogni blocco try, devono tenere traccia delle clausole catch associate e dei tipi di eccezioni che possono essere gestite da tali clausole.

Ci sono cose che si paga anche se non si usano mai funzioni di gestione delle eccezioni. Si paga lo spazio utilizzato dalle strutture dati necessarie per tenere traccia di quali oggetti sono completamente costruiti, e si paga per il tempo necessario a mantenere aggiornate queste strutture dati. Questi costi sono in genere piuttosto modesti.

Tuttavia, programmi compilati senza il supporto per le eccezioni sono in genere più veloce e più piccolo rispetto ai loro omologhi compilato con il supporto per le eccezioni

+4

Ma questo non risponde alla domanda. "Il compilatore con i suoi diritti" as-if "rimuoverà il try catch e si comporterà come se la chiamata' std :: uninitialized_copy' apparisse senza 'try' attorno ad esso?". In altre parole, tutto il lavoro che descrivi può essere eliminato, dal momento che il compilatore può (in linea di principio) vedere che non è necessario? –

0

Da 15,1/8 troviamo

una rimessa espressione senza genera nuovamente operandi l'eccezione attualmente gestita (15.3). L'eccezione viene riattivata con l'esistente temporaneo; nessun nuovo oggetto eccezione temporanea si crea ...

Per me questa abbastanza chiaramente implica che assumendo la valutazione di boost::has_trivial_destructor<T>::value banalmente può essere dimostrato di avere effetti collaterali che il compilatore dovrebbe essere in grado di determinare facilmente che l'intera massa del pescato non è eseguibile e l'intero costrutto può essere ottimizzato. Non sono specificamente consapevole di nessun compilatore che lo faccia/non lo faccia comunque.

Il mio solo (leggero) dubbio è se la lingua considera la compensazione e il ripristino di std::uncaught_exception() per rientrare nella clausola "come-se".

1

mi hanno alcuna idea di ciò che il compilatore fare, ma so che è possibile applicare l'ottimizzazione da soli:

template <class T> 
typename boost::enable_if_t<boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    std::uninitialized_copy(...); 
} 

template <class T> 
typename boost::enable_if_t<!boost::has_trivial_destructor<T>::value, void> 
wrap_uninitialized_copy (...) { 
    try { 
     std::uninitialized_copy(...); 
    } catch(...) { 
     // some cleanup to do here... 
     throw; 
    } 
}