Structured Bindings

Podczas ostatniego spotkania komitetu standaryzacyjnego w Oulu, do najnowszej wersji standardu zatwierdzono między innymi, tzw. structured bindings, czyli nowy sposób dekomponowania wartości:

auto [x, y, z] = f();

Powyższe jest równoważne następującemu wywołaniu std::tie:

T1 x; T2 y; T3 z;
std::tie(x,y,z) = f();

Nie chcę powtarzać przykładów z podlinkowanego dokumentu (polecam jego lekturę - jest niedługi i bardzo przejrzyście napisany), dlatego powiem tylko o dwóch rzeczach, które osobiście zaimponowały mi najbardziej.

Pierwszą jest użycie structured bindings razem z inną nowinką z Oulu, nową wersją if-a1, co skutkuje powstaniem bardzo przyjemnego, czytelnego kodu:

std::map<int, std::string> m;
if (auto [iter, success] = m.insert(val); success == true)
{
    // do sth
}
else
{
    // do sth else
}

Drugą natomiast jest użycie nowego konstruktu wewnątrz pętli range-for:

std::map<T1, T2> m;
for (const auto& [key, val] : m)
{ 
    ... 
}

Powyżej użyta została wersja structured bindings wespół z const referencją. W nowej składni wszystkie cv-qualifiers oraz referencje działają tak samo jak działałyby ze zwykłym auto. Oznacza to na przykład, że poniższe wyrażenie wydłuży czas życia zmiennych tymczasowych:

std::pair<int, string> foo()
{
    return std::make_pair(1, "abc"s);
}

const auto& [i, s] = foo();

Zaczyna to przypominać Pythona i inne wysokopoziomowe języki, prawda?


  1. W skrócie: zwykły if zostaje rozszerzony o możliwość wpisania niezależnego wyrażenia inicjalizującego: if (init; cond) ↩︎