Para aclarar el concepto central, reduzcamoslo a un ejemplo más básico. Aunque std::tie
es útil para funciones que devuelven (una tupla de) más valores, podemos entenderlo bien con un solo valor:
int a;
std::tie(a) = std::make_tuple(24);
return a; // 24
Cosas que debemos saber para seguir adelante:
El siguiente paso es deshacerse de esas funciones que solo se interponen en su camino, para que podamos transformar nuestro código a esto:
int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24
El siguiente paso es ver exactamente qué sucede dentro de esas estructuras. Para esto, creo 2 tipos de T
sustituyentes std::tuple<int>
y Tr
sustituyentes std::tuple<int&>
, reducidos al mínimo para nuestras operaciones:
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
}
Y finalmente, me gusta deshacerme de las estructuras todas juntas (bueno, no es 100% equivalente, pero es lo suficientemente cercano para nosotros y lo suficientemente explícito como para permitirlo):
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
}
Básicamente, std::tie(a)
inicializa una referencia de miembro de datos a a
. std::tuple<int>(24)
crea un miembro de datos con valor 24
, y la asignación asigna 24 a la referencia del miembro de datos en la primera estructura. Pero dado que ese miembro de datos es una referencia vinculada a a
, básicamente se asigna 24
a a
.