structured bindings (auto [a, b]) în C++

Desface o pereche, un tuplu, o structură sau un tablou în variabile separate, cu nume, într-o singură declarație.

Sintaxă
auto [a, b] = pereche;
const auto& [nume, nota] = element;
for (const auto& [cheie, valoare] : harta) { ... }

Ce face structured bindings (auto [a, b])

Înainte de C++17, pentru o pereche scriai p.first și p.second. Cu legăturile structurate (structured bindings) scrii auto [nume, varsta] = p; și primești două variabile cu nume clare.

Funcționează cu std::pair, std::tuple, tablouri, std::array și structuri cu membri publici, în ordinea membrilor. Cel mai des le vei vedea în buclele peste std::map: for (const auto& [cheie, valoare] : harta).

Numărul de nume dintre paranteze drepte trebuie să fie exact numărul de elemente. Cu auto& numele se referă la elementele originale, deci le poți modifica.

Exemple

Exemplul 1: Desfacerea unei structuri și a unei perechi

#include <print>
#include <string>
#include <utility>

struct Elev {
    std::string nume;
    int nota;
};

std::pair<int, int> imparte(int a, int b) {
    return {a / b, a % b};
}

int main() {
    Elev e{"Ana", 10};
    auto [nume, nota] = e;
    std::println("{} are nota {}", nume, nota);

    auto [cat, rest] = imparte(17, 5);
    std::println("17 / 5 = {} rest {}", cat, rest);
}

Rezultat

Ana are nota 10
17 / 5 = 3 rest 2

Exemplul 2: Parcurgerea unui map

#include <map>
#include <print>
#include <string>

int main() {
    std::map<std::string, int> populatie = {{"Iași", 271}, {"Cluj", 286}, {"Brașov", 237}};
    for (const auto& [oras, mii] : populatie) {
        std::println("{}: {} mii locuitori", oras, mii);
    }
}

Rezultat

Brașov: 237 mii locuitori
Cluj: 286 mii locuitori
Iași: 271 mii locuitori

Exemplul 3: Modificare prin referință

Cu auto&, x și y sunt chiar elementele tabloului, nu copii.

#include <print>

int main() {
    int punct[2] = {3, 4};
    auto& [x, y] = punct;
    x *= 10;
    y *= 10;
    std::println("Punct: ({}, {})", punct[0], punct[1]);
}

Rezultat

Punct: (30, 40)

Greșeli frecvente

  • Dai alt număr de nume decât elemente: auto [a, b] = std::tuple{1, 2, 3}; nu se compilează.
  • Scrii auto [x, y] și modifici x așteptându-te să se schimbe originalul. Fără &, lucrezi pe o copie.
  • Încerci să declari tipul fiecărui nume (auto [std::string nume, int nota]). Nu se poate: tipurile se deduc toate din auto.

Comenzi înrudite

  • auto: Lasă compilatorul să deducă tipul variabilei din valoarea cu care este inițializată.
  • range-for (for (x : colecție)): Parcurge pe rând toate elementele unei colecții (vector, tablou, string, map) fără index și fără iteratori scriși de mână.
  • struct: Grupează mai multe valori într-un singur tip; ca o clasă, dar cu membri publici implicit.
  • 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::pair: Grupează două valori, eventual de tipuri diferite, într-un singur obiect cu membrii first și second.
  • std::tuple: Grupează oricâte valori de tipuri diferite într-un singur obiect; generalizarea lui std::pair.
  • std::map: Dicționar ordonat: asociază fiecărei chei unice o valoare și păstrează cheile sortate.