Dal secondo capitolo: Tecniche
Asserzioni durante la compilazione.
Un problema nell'uso dei template in C++ è come assicurare la correttezza del codice. Diciamo di aver scritto una funzione template che rende più sicura la reinterpret_cast aggiungendo un asserzione:
template
To safe_reinterpret_cast(From from)
{
assert(sizeof(From) <= sizeof(To)); return reinterpret_cast(from);
}
Ora prima di eseguire una reinterpret_cast si verifica che il tipo in output sia di dimensione tale da non causare una perdita di byte significativi.
E' sicuramente un passo in avanti rispetto a una reinterpret_cast senza controllo ma sarebbe ancora meglio se potessimo fare il controllo in fase di compilazione e non esecuzione.
Per far questo ci viene in aiuto una macro, pensata da Van Horn che funziona bene anche in C usando il fatto che un array di dimensione zero è illegale:
#define STATIC_CHECK(expr) { char unnamed[(expr) ? 1 : 0]; }
Se l'espressione expr è "vera" la macro genera un array legale, altrimenti uno illegale, e quindi un errore in fase di compilazione.
Riscriviamo la funzione template in questo modo:
template
To checked_reinterpret_cast(From from)
{
STATIC_CHECK(sizeof(From) <= sizeof(To)); return reinterpret_cast(from);
}
Resta il problema della messaggistica generata. Usando STATIC_CHECK, in caso di errore abbiamo una segnalazione sulla dimensione zero dell'array, che non è in realtà molto pertinente con il nostro reale errore. L'Alexandrescu mostra una ingegnosa soluzione che ci permette di generare un messaggio significativo ma che, purtroppo, non è supportato da tutti i compilatori - ad esempio non da quello che sto usando correntemente.
Per cui mi accontento di STATIC_CHECK.
Nessun commento:
Posta un commento