Ответ 1
Чтобы прояснить основную концепцию, позвольте ее свести к более базовому примеру. Хотя std::tie
полезно для возвращающих функций (кортежей) большего числа значений, мы можем понять это просто отлично только с одним значением:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
Вещи, которые нам нужно знать, чтобы идти вперед:
-
std::tie
строит и возвращает кортеж ссылок. -
std::tuple<int>
иstd::tuple<int&>
- 2 совершенно разных класса, без связи между ними, другие, которые были сгенерированы из одного и того же шаблона,std::tuple
. -
tuple имеет
operator=
, принимающий кортеж разных типов (но тот же номер), где каждый член назначается индивидуально - из cppreference:template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );
(3) Для всех я присваивает
std::get<i>(other)
-std::get<i>(*this)
.
Следующий шаг - избавиться от тех функций, которые только мешают вам, поэтому мы можем преобразовать наш код в это:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
Следующий шаг - посмотреть, что именно происходит внутри этих структур.
Для этого я создаю 2 типа 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
.