Static assert ist ein Mechanismus des Compilers zur Generierung von Fehlern zur Compile-Zeit, wenn der Ausdruck (Bedingung) nicht erfüllt ist. Die Funktionalität wurde ab C++11 hinzugefügt, um die Programmierung von Vorlagen zu erleichtern und die Codequalität zu verbessern.
Geschichte der Frage.
Vor der Einführung von static_assert verwendeten Programmierer Tricks wie Strukturen mit negativem Array-Größe (zum Beispiel char arr[condition?1:-1];), was weniger lesbar und weniger praktisch zur Fehlerdiagnose war. So entstand der Bedarf an einer expliziten Deklaration von Compile-Zeitfehlern mit sinnvollen Meldungen.
Problem.
In der Vorlagenprogrammierung besteht oft die Notwendigkeit einer frühen Diagnose (zum Beispiel ein Verbot zur Erstellung eines Objekts mit einem ungeeigneten Typ oder Parameter). Ohne statische Überprüfung traten solche Fehler erst in der Phase der Kompilierung des endgültigen Codes auf (manchmal als plötzlicher und schlecht erklärter Fehler).
Lösung.
Das Schlüsselwort static_assert nimmt einen booleschen Ausdruck und eine Nachrichtenzeichenfolge entgegen. Wenn der Ausdruck falsch ist, wird die Kompilierung mit einer Fehlermeldung abgebrochen.
Beispielcode:
static_assert(sizeof(int) >= 4, "int muss mindestens 4 Bytes groß sein"); template<typename T> void foo(const T& obj) { static_assert(std::is_copy_constructible<T>::value, "T muss kopierbar sein"); }
Schlüsselfunktionen:
Kann man static_assert ohne das zweite Argument verwenden?
Ja, seit C++17 ist das zweite Argument optional:
static_assert(sizeof(double) == 8); // Meldung ist standardmäßig
Wird static_assert ausgeführt, wenn die Bedingung von Vorlagenparametern abhängt, die Vorlage aber nicht instanziiert wird?
Nein, static_assert wird nur ausgelöst, wenn der Instanziierungspunkt erreicht wird, was es erlaubt, Überprüfungen nur für verwendete Vorlagen anzuwenden.
Kann man Laufzeitausdrücke (run-time) innerhalb von static_assert verwenden?
Nein, der Ausdruck muss zur Compile-Zeit berechenbar sein (constexpr). Wenn der Ausdruck nicht constexpr ist, gibt es einen Kompilierungsfehler.
Im Code wurde static_assert mit einem Ausdruck verwendet, der nur zur Laufzeit berechnet wird (zum Beispiel die Dateigröße beim Einlesen), was zu einem unverständlichen Kompilierungsfehler im gesamten System führte.
Vorteile:
Nachteile:
Es ist erforderlich zu garantieren, dass die Vorlage Matrix nur mit Plain Old Data (POD) Typen erstellt werden kann, komplexe Strukturen ausschließend.
template<typename T> class Matrix { static_assert(std::is_pod<T>::value, "Matrix kann nur für POD-Typen instanziiert werden"); // ... };
Vorteile:
Nachteile: