Чтобы прояснить основную концепцию, давайте сведем ее к более простому примеру. Хотя 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
.