tutorial studio means example clusters clustering cluster analisis c++ c++11 tuples

c++ - studio - ¿Cómo funciona std:: tie?



hclust r tutorial (2)

Esto no responde a su pregunta de ninguna manera, pero permítame publicarlo de todos modos porque C ++ 17 está básicamente listo (con soporte de compilador), por lo que mientras se pregunta cómo funciona el material desactualizado, probablemente valga la pena ver cómo funciona. futuro, la versión de C ++ también funciona.

Con C ++ 17 puedes rascar bastante std::tie a favor de lo que se llama enlaces estructurados . Hacen lo mismo (bueno, no lo mismo , pero tienen el mismo efecto neto), aunque necesita escribir menos caracteres, no necesita soporte de biblioteca, y también tiene la capacidad de tomar referencias, si eso sucede. Lo que quieras.

(Tenga en cuenta que en C ++ 17 los constructores hacen la deducción de argumentos, por lo que make_tuple ha vuelto algo superfluo).

int a, b; std::tie(a, b) = std::make_tuple(2, 3); // C++17 auto [c, d] = std::make_tuple(4, 5); auto [e, f] = std::tuple(6, 7); std::tuple t(8,9); auto& [g, h] = t; // not possible with std::tie

He usado std::tie sin pensarlo mucho. Funciona, así que acabo de aceptar que:

auto test() { int a, b; std::tie(a, b) = std::make_tuple(2, 3); // a is now 2, b is now 3 return a + b; // 5 }

¿Pero cómo funciona esta magia negra ? ¿Cómo un temporal creado por std::tie cambia b ? Esto me parece más interesante ya que es una función de biblioteca, no una función de lenguaje, por lo que seguramente es algo que podemos implementar y comprender.


Para aclarar el concepto central, redujémoslo 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 solo un valor:

int a; std::tie(a) = std::make_tuple(24); return a; // 24

Cosas que necesitamos saber para seguir adelante:

  • std::tie construye y devuelve una tupla de referencias.
  • std::tuple<int> y std::tuple<int&> son 2 clases completamente diferentes, sin conexión entre ellas, aparte de que se generaron a partir de la misma plantilla, std::tuple .
  • tupla tiene un operator= aceptar una tupla de diferentes tipos (pero el mismo número), donde cada miembro se asigna individualmente, desde cppreference :

    template< class... UTypes > tuple& operator=( const tuple<UTypes...>& other );

    (3) Para todo i, asigna std::get<i>(other) a std::get<i>(*this) .

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 sustituyentes T para std::tuple<int> y sustituyentes Tr std::tuple<int&> , despojados 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 todas las estructuras (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 , que básicamente asigna 24 a a .