std::enable_if în C++

Activează o funcție-șablon doar pentru tipurile care îndeplinesc o condiție (tehnica SFINAE).

Sintaxă
#include <type_traits>
template<bool Conditie, class T = void>
struct enable_if;
std::enable_if_t<Conditie, T>   // C++14

Ce face std::enable_if

std::enable_if_t<conditie, T> este tipul T dacă condiția este adevărată și nu există deloc dacă este falsă. Pus în semnătura unui șablon, face ca funcția să „dispară” pentru tipurile care nu îndeplinesc condiția, iar compilatorul alege altă variantă sau dă eroare. Regula din spate se numește SFINAE („eșecul substituției nu este o eroare”).

Este tehnica clasică din C++11/14/17. În C++20 conceptele și requires fac același lucru mult mai clar (vezi std::integral), dar enable_if apare foarte des în cod existent.

Parametri

Parametru Descriere
Conditie Expresie bool evaluată la compilare.
T Tipul rezultat când condiția este adevărată (implicit void).

Ce returnează

Tipul T, dacă Conditie este adevărată.

Exemple

Exemplul 1: Două variante ale aceleiași funcții

Pentru fiecare apel, doar una dintre cele două funcții există, în funcție de tipul argumentului.

#include <print>
#include <type_traits>

template <class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
void afiseaza(T x) {
    std::println("întreg: {}", x);
}

template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
void afiseaza(T x) {
    std::println("real: {:.3f}", x);
}

int main() {
    afiseaza(42);
    afiseaza(3.14159);
    // afiseaza("text");   // nu compilează: nicio variantă nu se potrivește
}

Rezultat

întreg: 42
real: 3.142

Exemplul 2: Același lucru cu un concept (C++20)

#include <concepts>
#include <print>

void afiseaza(std::integral auto x) { std::println("întreg: {}", x); }
void afiseaza(std::floating_point auto x) { std::println("real: {:.3f}", x); }

int main() {
    afiseaza(42);
    afiseaza(3.14159);
}

Rezultat

întreg: 42
real: 3.142

Greșeli frecvente

  • Pui enable_if în două funcții care diferă doar prin argumentul implicit (class = std::enable_if_t<...>). Compilatorul le vede ca redeclarări ale aceleiași funcții; folosește forma std::enable_if_t<..., int> = 0.

Comenzi înrudite

  • std::integral: Concepte C++20 care restrâng un șablon la tipuri întregi (integral) sau reale (floating_point).
  • std::is_integral: is_integral verifică dacă un tip este întreg (inclusiv bool și char); is_floating_point, dacă este real.
  • requires: Scrie cerințe pentru parametrii unui șablon: ca clauză care restrânge șablonul sau ca expresie care verifică dacă un cod este valid.
  • 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.