Static assert is een mechanisme van de compiler voor het genereren van fouten tijdens de compilatiefase, als een expressie (voorwaarde) niet waar is. Deze functionaliteit is toegevoegd vanaf C++11 om het programmeren met templates te vergemakkelijken en de codekwaliteit te verbeteren.
Geschiedenis van de vraag.
Voordat static_assert bestond, gebruikten programmeurs trucs zoals structuren met een negatieve arraygrootte (bijvoorbeeld char arr[condition?1:-1];), wat minder leesbaar en minder handig was voor foutdiagnose. Dit leidde tot de behoefte aan expliciete declaratie van compileertijdfouten met zinvolle berichten.
Probleem.
Bij templateprogrammering ontstaat vaak de noodzaak van vroege diagnose (bijvoorbeeld het verbieden van het creëren van een object met een ongepast type of parameter). Zonder statische controle kwamen dergelijke fouten pas naar voren in de fase van het compileren van de eindcode (soms als een plotselinge en slecht verklaarbare fout).
Oplossing.
Het sleutelwoord static_assert neemt een booleaanse expressie en een foutmelding als string. Als de expressie onwaar is, wordt de compilatie beëindigd met een foutmelding.
Voorbeeldcode:
static_assert(sizeof(int) >= 4, "int moet minstens 4 bytes zijn"); template<typename T> void foo(const T& obj) { static_assert(std::is_copy_constructible<T>::value, "T moet kopieerbaar zijn"); }
Belangrijke kenmerken:
Kan static_assert zonder het tweede argument gebruikt worden?
Ja, vanaf C++17 is het tweede argument optioneel:
static_assert(sizeof(double) == 8); // standaard bericht zal gebruikt worden
Worden static_assert expressies uitgevoerd als de voorwaarde afhankelijk is van templateparameters, maar de template wordt niet geïnstantieerd?
Nee, static_assert triggert alleen als het de instantiatiepunt bereikt, wat controles toelaat voor alleen gebruikte templates.
Kunnen runtime expressies binnen static_assert gebruikt worden?
Nee, de expressie moet berekenbaar zijn tijdens de compilatie (constexpr). Als de expressie niet constexpr is, is er een compilatiefout.
In de code werd static_assert gebruikt met een expressie die alleen in runtime berekend kon worden (bijvoorbeeld de bestandsgrootte bij het inlezen), wat leidde tot een onbegrijpelijke compilatiefout in het hele systeem.
Voordelen:
Nadelen:
Het is vereist om te garanderen dat de template Matrix alleen kan worden geïnstantieerd met Plain Old Data (POD) types, waarbij complexe structuren worden uitgesloten.
template<typename T> class Matrix { static_assert(std::is_pod<T>::value, "Matrix kan alleen voor POD-types worden geïnstantieerd"); // ... };
Voordelen:
Nadelen: