Para esclarecer o conceito central, vamos reduzi-lo a um exemplo mais básico. Embora std::tie
seja útil para funções que retornam (uma tupla de) mais valores, podemos entendê-lo perfeitamente com apenas um valor:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
Coisas que precisamos saber para seguir em frente:
A próxima etapa é se livrar dessas funções que apenas atrapalham seu caminho, para que possamos transformar nosso código para o seguinte:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
A próxima etapa é ver exatamente o que acontece dentro dessas estruturas. Para isso, crio 2 tipos de T
substituintes std::tuple<int>
e Tr
substituintes std::tuple<int&>
, reduzidos ao mínimo para nossas operações:
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
}
E, finalmente, gosto de me livrar das estruturas todas juntas (bem, não é 100% equivalente, mas é próximo o suficiente para nós e explícito o suficiente para permitir):
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
}
Então, basicamente, std::tie(a)
inicializa uma referência de membro de dados para a
. std::tuple<int>(24)
cria um membro de dados com valor 24
e a atribuição atribui 24 à referência do membro de dados na primeira estrutura. Mas, como esse membro de dados é um limite de referência a
, basicamente atribui 24
a a
.