← SEARCHABLE ARCHIVE
C / C++ · 2026-08-11

C++ von den Grundlagen bis zum Profi — Folge 17

Mit constexpr und consteval zur Compile-Zeit rechnen

INTERACTIVE READING MODE →

Die Artikel in diesem Blog wurden zu Lehrzwecken verfasst. Sie können Fehler enthalten; prüfen Sie die Aussagen daher mit dem Ziel-Compiler und der verwendeten Standardbibliothek.

C++ kann ausgewählte Berechnungen vor dem Programmstart ausführen. constexpr, consteval und constinit stehen für unterschiedliche Verträge: mögliche Konstantenauswertung, zwingende Compile-Zeit-Aufrufe und statische Initialisierung.

constexpr funktioniert in zwei Kontexten

constexpr int Square(int value)
{
    return value * value;
}

constexpr int tableSize = Square(8); // Compile-Zeit
int input = ReadInput();
int result = Square(input);          // Laufzeit

Eine constexpr-Funktion kann konstant ausgewertet werden, muss es aber nicht bei jedem Aufruf. Sind die Argumente konstant und wird das Ergebnis an einer Stelle mit erforderlichem constant expression benutzt, wertet der Compiler es dort aus.

consteval erzwingt die Compile-Zeit

consteval unsigned int HashLiteral(std::string_view text)
{
    unsigned int hash = 2166136261u;
    for (char ch : text)
        hash = (hash ^ static_cast<unsigned char>(ch)) * 16777619u;
    return hash;
}

constexpr auto playerId = HashLiteral("Player");

Jeder consteval-Aufruf muss ein constant expression sein. Das eignet sich für Asset-Schlüssel oder Protokoll-Tags, die beim Build feststehen müssen.

Ein Hash kann dennoch kollidieren. Compile-Zeit-Berechnung garantiert keine Eindeutigkeit; Kollisionsstrategie und Prüfung des Originalschlüssels bleiben nötig.

Ungültige Zweige mit if constexpr entfernen

template <typename T>
void Serialize(const T& value, Writer& writer)
{
    if constexpr (std::integral<T>)
        writer.WriteInteger(value);
    else
        value.Serialize(writer);
}

Anders als bei if wird der nicht gewählte if constexpr-Zweig für diese Instanz verworfen. Operationen, die für den gewählten Typ nicht existieren, müssen im anderen Zweig daher nicht gültig sein.

constinit prüft statische Initialisierung

constinit int globalLimit = 64;

constinit stellt die statische Initialisierung eines Objekts mit static storage duration sicher. Es macht das Objekt nicht unveränderlich; dafür ist const zuständig.

Compile-Zeit-Arbeit kann Laufzeitinitialisierung vermeiden und Fehler früher melden, erhöht aber Build-Zeit, Diagnoseaufwand und teilweise die Binärgröße. Setzen Sie sie ein, wenn eine Regel wirklich feststeht und die frühe Prüfung ihren Preis wert ist.