Static check

Appunti presi durante la lettura di Modern C++ Design: Generic Programming and Design Patterns Applied, di Andrei Alexandrescu.

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