Static assert è un meccanismo del compilatore per generare errori in fase di compilazione se un'espressione (condizione) non è soddisfatta. Questa funzionalità è stata introdotta a partire da C++11 per semplificare la programmazione dei template e migliorare la qualità del codice.
Storia della questione.
Prima dell'introduzione di static_assert, i programmatori usavano trucchi come strutture con dimensioni negative di array (tipo char arr[condition?1:-1];), il che era meno leggibile e meno comodo per diagnosticare errori. Così nacque la necessità di dichiarare esplicitamente gli errori di tempo di compilazione con messaggi significativi.
Problema.
Nella programmazione dei template, spesso sorge la necessità di una diagnosi precoce (ad esempio, vietare la creazione di un oggetto di tipo o parametro non adatto). Senza il controllo statico, tali errori apparivano solo nella fase di compilazione del codice finale (a volte come errori inaspettati e mal spiegati).
Soluzione.
La parola chiave static_assert accetta un'espressione booleana e una stringa di messaggio. Se l'espressione è falsa, la compilazione termina con un errore e il messaggio viene visualizzato.
Esempio di codice:
static_assert(sizeof(int) >= 4, "int deve essere almeno di 4 byte"); template<typename T> void foo(const T& obj) { static_assert(std::is_copy_constructible<T>::value, "T deve essere copiabile"); }
Caratteristiche principali:
È possibile usare static_assert senza il secondo argomento?
Sì, a partire da C++17 il secondo argomento è opzionale:
static_assert(sizeof(double) == 8); // il messaggio sarà per default
Vengono eseguite le espressioni static_assert se la condizione dipende dai parametri del template, ma il template non è istanziato?
No, static_assert scatta solo se raggiunge il punto di istanziazione, consentendo di applicare controlli solo per i template utilizzati.
È possibile utilizzare espressioni a tempo di esecuzione all'interno di static_assert?
No, l'espressione deve essere valutabile in fase di compilazione (constexpr). Se l'espressione non è constexpr, si verifica un errore di compilazione.
Nel codice è stato utilizzato static_assert con un'espressione valutabile solo a runtime (ad esempio, la dimensione di un file in lettura), il che ha generato un errore di compilazione incomprensibile in tutto il sistema.
Pro:
Contro:
È necessario garantire che il template Matrix possa essere creato solo con tipi Plain Old Data (POD), escludendo strutture complesse.
template<typename T> class Matrix { static_assert(std::is_pod<T>::value, "Matrix può essere istanziato solo per tipi POD"); // ... };
Pro:
Contro: