Ce face constexpr
O variabilă constexpr este o constantă a cărei valoare trebuie cunoscută în momentul compilării. O poți folosi oriunde limbajul cere o constantă: mărimea unui std::array, un argument de șablon, un static_assert.
O funcție constexpr poate fi calculată de compilator când primește argumente constante, iar rezultatul ajunge direct în program, fără calcul la rulare. Cu argumente cunoscute doar la rulare, funcționează ca o funcție obișnuită.
Regulile s-au relaxat la fiecare standard: în C++11 o funcție constexpr putea avea doar un return; din C++14 poate avea bucle și variabile; din C++20 poate folosi chiar std::vector și std::string (temporar, în timpul calculului).
Exemple
Exemplul 1: Constante pentru mărimi
#include <array>
#include <print>
constexpr int ZILE = 7;
constexpr double PI = 3.14159265358979;
int main() {
std::array<int, ZILE> temperaturi = {12, 14, 15, 13, 16, 18, 17};
std::println("Zile măsurate: {}", temperaturi.size());
std::println("Aria cercului cu raza 2: {:.4f}", PI * 2 * 2);
}
Rezultat
Zile măsurate: 7
Aria cercului cu raza 2: 12.5664
Exemplul 2: Funcție calculată la compilare
static_assert verifică rezultatul în timpul compilării: dacă factorial(5) n-ar fi 120, programul nici nu s-ar compila. Aceeași funcție este apoi folosită la rulare.
#include <print>
constexpr long long factorial(int n) {
long long rezultat = 1;
for (int i = 2; i <= n; ++i) {
rezultat *= i;
}
return rezultat;
}
int main() {
constexpr long long f5 = factorial(5); // calculat de compilator
static_assert(f5 == 120);
std::println("5! = {}", f5);
int n = 10; // valoare de la rulare
std::println("{}! = {}", n, factorial(n));
}
Rezultat
5! = 120
10! = 3628800
Exemplul 3: Tabel generat la compilare
Tabloul de pătrate este construit în întregime de compilator; la rulare doar se afișează.
#include <array>
#include <print>
constexpr std::array<int, 6> patrate() {
std::array<int, 6> t{};
for (int i = 0; i < 6; ++i) {
t[i] = i * i;
}
return t;
}
constexpr auto TABEL = patrate();
int main() {
for (int valoare : TABEL) {
std::print("{} ", valoare);
}
std::println("");
}
Rezultat
0 1 4 9 16 25
Greșeli frecvente
- Inițializezi o variabilă
constexprcu o valoare de la rulare (constexpr int n = citeste();). Compilatorul refuză: pentru asta foloseșteconst. - Crezi că o funcție
constexprrulează mereu la compilare. Doar când rezultatul este cerut într-un context constant; altfel poate rula normal. Dacă vrei garanția, foloseșteconsteval.
Comenzi înrudite
const: Marchează o valoare care nu mai poate fi modificată după inițializare; compilatorul oprește orice încercare de schimbare.consteval: Definește o funcție imediată: fiecare apel trebuie calculat la compilare, altfel programul nu se compilează.constinit: Garantează că o variabilă globală sau statică este inițializată la compilare, dar fără să o facă constantă.if constexpr: Un if evaluat la compilare: ramura falsă este eliminată complet, deci poate conține cod care nu s-ar compila pentru tipul curent.static_assert: Verifică o condiție la compilare; dacă este falsă, compilarea se oprește cu mesajul dat.