static_assert în C++

Șabloane (template) și concepte C++11 (fără mesaj: C++17)

Verifică o condiție la compilare; dacă este falsă, compilarea se oprește cu mesajul dat.

Sintaxă
static_assert(condiție, "mesaj");
static_assert(condiție);   // C++17

Ce face static_assert

static_assert este o verificare făcută de compilator, nu de program. Condiția trebuie să fie cunoscută la compilare: mărimi de tipuri, proprietăți ale tipurilor (std::is_integral_v<T>), rezultate ale funcțiilor constexpr.

Dacă condiția este adevărată, nu se întâmplă nimic și nu se generează niciun cod. Dacă este falsă, compilarea eșuează cu mesajul tău, deci problema este găsită înainte ca programul să existe. Mesajul este opțional din C++17.

Este util în șabloane (pentru a da erori clare), pentru a verifica presupuneri despre platformă (de exemplu că int are 4 octeți) și ca teste rapide pentru funcții constexpr.

Exemple

Exemplul 1: Verificări despre platformă și despre calcule

Toate condițiile sunt adevărate, deci programul se compilează și rulează. Dacă una ar fi falsă, nu ar exista niciun program de rulat.

#include <print>

constexpr int zile_in_an(bool bisect) { return bisect ? 366 : 365; }

static_assert(sizeof(int) == 4, "codul presupune int pe 4 octeți");
static_assert(zile_in_an(true) == 366);
static_assert(zile_in_an(false) == 365);

int main() {
    std::println("Verificările de la compilare au trecut.");
}

Rezultat

Verificările de la compilare au trecut.

Exemplul 2: Mesaj clar într-un șablon

Dacă cineva ar apela medie cu un vector de std::string, compilarea s-ar opri cu mesajul „medie() cere numere”.

#include <print>
#include <type_traits>
#include <vector>

template <typename T>
double medie(const std::vector<T>& v) {
    static_assert(std::is_arithmetic_v<T>, "medie() cere numere");
    double suma = 0;
    for (const T& x : v) suma += x;
    return suma / v.size();
}

int main() {
    std::println("Media: {}", medie(std::vector<int>{7, 8, 10}));
}

Rezultat

Media: 8.333333333333334

Greșeli frecvente

  • Pui în static_assert o valoare cunoscută doar la rulare (static_assert(n > 0) cu n citit de la tastatură). Nu se compilează; pentru verificări la rulare folosește assert sau if.
  • Scrii static_assert(false, "...") într-o ramură de șablon care nu ar trebui folosită. Până la C++23 (unde regula a fost relaxată) compilatoarele pot da eroare chiar dacă ramura nu este folosită; folosește o condiție care depinde de T.

Comenzi înrudite

  • constexpr: Cere ca o valoare să fie calculată la compilare; o funcție constexpr poate rula atât la compilare, cât și la rulare.
  • concept: Dă un nume unui set de cerințe pentru tipuri, folosit ca să restrângi ce tipuri acceptă un șablon.
  • template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.
  • sizeof: Dă numărul de octeți ocupați în memorie de un tip sau de o variabilă; se calculează la compilare.
  • assert: Verifică o condiție care trebuie să fie mereu adevărată; dacă e falsă, oprește programul cu un mesaj.
  • std::is_same: Verifică la compilare dacă două tipuri sunt exact același tip.