decltype în C++

Dă tipul exact al unei expresii, fără să o evalueze; util pentru a declara variabile „de același tip ca”.

Sintaxă
decltype(expresie) nume;
decltype(auto) functie() { ... }   // C++14

Ce face decltype

decltype(x) înseamnă „tipul lui x”. Poți scrie decltype(pret) reducere = 0; ca să ai o variabilă exact de tipul lui pret. Expresia dintre paranteze nu este executată, doar analizată.

Spre deosebire de auto, decltype păstrează const și referințele. O capcană: decltype(x) dă tipul declarat al lui x, dar decltype((x)), cu paranteze duble, dă o referință.

decltype(auto) (C++14) deduce tipul cu regulile lui decltype; este folosit în funcții care trebuie să returneze exact ce returnează altă funcție, inclusiv referințe.

Exemple

Exemplul 1: Variabilă de același tip ca alta

#include <print>

int main() {
    double pret = 120.5;
    decltype(pret) reducere = 20.25;
    std::println("Preț final: {}", pret - reducere);
    long long vizite = 3'000'000'000;
    decltype(vizite) dublu = vizite * 2;
    std::println("Dublu: {}", dublu);
}

Rezultat

Preț final: 100.25
Dublu: 6000000000

Exemplul 2: decltype păstrează const și referința

auto ar fi dat int în ambele cazuri; decltype dă tipul exact.

#include <print>
#include <type_traits>

int main() {
    const int maxim = 10;
    int nota = 9;
    int& ref = nota;
    std::println("decltype(maxim) e const int: {}", std::is_same_v<decltype(maxim), const int>);
    std::println("decltype(ref) e int&: {}", std::is_same_v<decltype(ref), int&>);
    std::println("decltype((nota)) e int&: {}", std::is_same_v<decltype((nota)), int&>);
    std::println("decltype(nota + 1) e int: {}", std::is_same_v<decltype(nota + 1), int>);
}

Rezultat

decltype(maxim) e const int: true
decltype(ref) e int&: true
decltype((nota)) e int&: true
decltype(nota + 1) e int: true

Exemplul 3: Expresia nu este executată

Funcția din decltype nu este apelată, deci mesajul ei nu apare; contează doar tipul returnat.

#include <print>

int calcul_scump() {
    std::println("calcul_scump a rulat");
    return 42;
}

int main() {
    decltype(calcul_scump()) x = 7;
    std::println("x = {}", x);
}

Rezultat

x = 7

Greșeli frecvente

  • Pui paranteze în plus: decltype((x)) dă int&, nu int. O variabilă declarată cu acest tip devine o referință și trebuie inițializată.
  • Folosești decltype unde merge auto. Pentru variabile obișnuite auto e mai simplu; decltype e util mai ales în șabloane.

Comenzi înrudite

  • auto: Lasă compilatorul să deducă tipul variabilei din valoarea cu care este inițializată.
  • typeid: Dă informații despre tipul unei expresii la rulare; pentru clase cu funcții virtuale arată tipul real al obiectului.
  • template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.
  • referințe (&, &&): O referință este un alt nume pentru o variabilă existentă; tot ce faci cu referința se face de fapt cu variabila originală.
  • std::is_same: Verifică la compilare dacă două tipuri sunt exact același tip.