Щоб уточнити основну концепцію, зведемо її до більш базового прикладу. Хоча std::tie
це корисно для функцій, що повертають (кортеж) більше значень, ми можемо зрозуміти це просто чудово лише з одним значенням:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
Те, що нам потрібно знати, щоб йти вперед:
Наступним кроком є позбавлення від тих функцій, які лише перешкоджають вам, і ми можемо перетворити наш код на це:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
Наступний крок - точно зрозуміти, що відбувається всередині цих структур. Для цього я створюю два типи T
заступника std::tuple<int>
і Tr
заступника std::tuple<int&>
, позбавленого мінімуму для наших операцій:
struct T { // substituent for std::tuple<int>
int x;
};
struct Tr { // substituent for std::tuple<int&>
int& xr;
auto operator=(const T& other)
{
// std::get<I>(*this) = std::get<I>(other);
xr = other.x;
}
};
auto foo()
{
int a;
Tr{a} = T{24};
return a; // 24
}
І нарешті, мені подобається позбутися від структур усі разом (ну, це не 100% еквівалент, але для нас це досить близько і явно, щоб це допустити):
auto foo()
{
int a;
{ // block substituent for temporary variables
// Tr{a}
int& tr_xr = a;
// T{24}
int t_x = 24;
// = (asignement)
tr_xr = t_x;
}
return a; // 24
}
Отже, std::tie(a)
ініціалізує посилання члена даних на a
. std::tuple<int>(24)
створює член даних зі значенням 24
, і призначення призначає 24 посилання члена даних у першій структурі. Але оскільки цей елемент даних є посилання зобов'язана a
, що в основному правонаступники 24
до a
.