Metaprogramarea pe bază de șabloane (Template Metaprogramming) a fost întotdeauna una dintre cele mai puternice capabilități ale limbajului C++, dar și una dintre cele mai detestate din cauza sintaxei criptice bazate pe std::enable_if (idiomul SFINAE) și a erorilor de compilare de mii de linii indescifrabile. Standardul C++20 a transformat radical acest peisaj prin introducerea Conceptelor (Concepts): constrângeri formale, lizibile și de tip sigur verificate la timpul compilării.
1. Definirea și Utilizarea Propriilor Concepte
Un concept este o expresie booleană evaluată la timpul compilării care validează dacă un tip de date respectă un set de operațiuni (are anumite metode, permite anumiți operatori sau returnează anumite tipuri):
#include <concepts>
#include <string>
#include <print>
// Definim conceptul 'Serializabil':
template <typename T>
concept Serializabil = requires(T a) {
{ a.toJson() } -> std::same_as<std::string>; // Tipul trebuie să aibă o metodă toJson() ce returnează string
};
// Sintaxă concisă C++20 direct în lista de parametri:
void salveazaInBazaDeDate(const Serializabil auto& obiect) {
std::println("Payload salvat: {}", obiect.toJson());
}
struct Utilizator {
std::string nume;
std::string toJson() const { return "{"nume": "" + nume + ""}"; }
};
struct ProdusFaraJson {
int pret;
};
int main() {
Utilizator u{"Maria"};
salveazaInBazaDeDate(u); // ✅ Compilează perfect!
// ProdusFaraJson p{100};
// salveazaInBazaDeDate(p);
// ❌ Eroare de compilare curată: "constraints not satisfied: 'a.toJson()' is invalid"
return 0;
}
2. constexpr vs consteval vs constinit
3. Ramificare la Compilare cu if constexpr
Directiva if constexpr permite scrierea de algoritmi generici care se adaptează instantaneu la tipul primit, compilatorul eliminând complet ramurile neutilizate din binarul final:
template <typename T>
void afiseazaDetalii(const T& val) {
if constexpr (std::is_pointer_v<T>) {
std::println("Adresa pointer: {}", static_cast<const void*>(val));
} else {
std::println("Valoare directa: {}", val);
}
}