Ce face if constexpr
if constexpr se folosește mai ales în șabloane (template). Condiția trebuie cunoscută la compilare, de exemplu o întrebare despre tip: std::is_integral_v<T>. Compilatorul păstrează doar ramura adevărată; cealaltă nu este nici măcar verificată pentru tipul respectiv.
Cu un if obișnuit, ambele ramuri trebuie să fie cod valid pentru fiecare tip. De exemplu, nu poți apela .size() pe un int, nici măcar într-o ramură care nu se execută. Cu if constexpr, poți.
Înlocuiește multe tehnici vechi și greu de citit (SFINAE, std::enable_if, specializări separate).
Exemple
Exemplul 1: Comportament diferit după tip
Pentru int ramura cu .size() este eliminată; pentru std::string este eliminată ramura cu numere. Cu un if obișnuit, codul nu s-ar compila.
#include <print>
#include <string>
#include <type_traits>
template <typename T>
void descrie(const T& valoare) {
if constexpr (std::is_integral_v<T>) {
std::println("{} este un număr întreg, dublul lui: {}", valoare, valoare * 2);
} else if constexpr (std::is_same_v<T, std::string>) {
std::println("\"{}\" este un text cu {} caractere", valoare, valoare.size());
} else {
std::println("{} este alt tip", valoare);
}
}
int main() {
descrie(21);
descrie(std::string("Cluj"));
descrie(3.5);
}
Rezultat
21 este un număr întreg, dublul lui: 42
"Cluj" este un text cu 4 caractere
3.5 este alt tip
Exemplul 2: Recursivitate pe argumente variabile
if constexpr oprește recursivitatea când nu mai sunt argumente; fără el ar trebui o funcție separată pentru cazul de oprire.
#include <print>
template <typename Primul, typename... Restul>
void afiseaza_tot(const Primul& primul, const Restul&... restul) {
std::print("{}", primul);
if constexpr (sizeof...(restul) > 0) {
std::print(", ");
afiseaza_tot(restul...);
} else {
std::println("");
}
}
int main() {
afiseaza_tot("Ana", 10, 9.5, 'A');
}
Rezultat
Ana, 10, 9.5, A
Greșeli frecvente
- Folosești în condiție o valoare cunoscută doar la rulare (
if constexpr (n > 5)cunparametru obișnuit). Nu se compilează; condiția trebuie să fie constantă. - Folosești
if constexprîn afara unui șablon și te aștepți ca ramura falsă să nu fie verificată. În cod obișnuit (non-șablon), ambele ramuri sunt verificate de compilator.
Comenzi înrudite
if, else: Execută un bloc de cod doar dacă o condiție este adevărată; else oferă varianta pentru cazul contrar.template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.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.std::is_same: Verifică la compilare dacă două tipuri sunt exact același tip.std::enable_if: Activează o funcție-șablon doar pentru tipurile care îndeplinesc o condiție (tehnica SFINAE).