Una tupla de C++ es un contenedor que puede almacenar múltiples valores de múltiples tipos en él. Podemos acceder a los elementos de la tupla usando std::get() , pero std::get() siempre toma un parámetro de variable constante, por lo que no podemos simplemente iterarlo usando un bucle. Para tareas que requieren iterar a través de todos los elementos de la tupla. como imprimir todos los elementos.
A continuación se muestra el programa para ilustrar la iteración sobre una tupla de elementos:
CPP14
// C++ program to iterate over the // elements of an std::tuple // using std:get() #include <iostream> #include <string> #include <tuple> // Driver Code int main() { // Declare a tuple and initialize // it using its constructor std::tuple<std::string, std::string, std::string> tup("Geeks", "for", "Geeks"); std::cout << "Values of tuple: "; // std::get is used to access // the value of tuple. std::cout << std::get<0>(tup) << " " << std::get<1>(tup) << " " << std::get<2>(tup) << std::endl; // Make the tuple using // std::make_tuple function tup = std::make_tuple("Hey", "Welcome to", "Geeksforgeeks"); // Print tuple std::cout << "Values of tuple(Modified): "; std::cout << std::get<0>(tup) << " " << std::get<1>(tup) << " " << std::get<2>(tup) << std::endl; return 0; }
Values of tuple: Geeks for Geeks Values of tuple(Modified): Hey Welcome to Geeksforgeeks
El problema surge cuando tratamos de iterar a través de toda la tupla. Entonces, tenemos dos métodos aquí, para iterar a través de los valores de una tupla:
- Uso de plantillas Variadic y metaprogramación (sin uso de std::apply).
- Uso de plantillas Variadic y std::apply.
Usando Plantillas Variádicas y Plantilla :
Las plantillas variádicas se usan para pasar múltiples argumentos empaquetados en un argumento de plantilla, y eso se puede expandir más tarde dentro de la función. Así es como revisaremos todos los elementos de una tupla.
A continuación se muestra la implementación del mismo:
CPP
// C++ program to iterated thorough // all values. I equals number // of values in tuple #include <iostream> #include <string> #include <tuple> using namespace std; // Function to iterate through all values // I equals number of values in tuple template <size_t I = 0, typename... Ts> typename enable_if<I == sizeof...(Ts), void>::type printTuple(tuple<Ts...> tup) { // If iterated through all values // of tuple, then simply return. return; } template <size_t I = 0, typename... Ts> typename enable_if<(I < sizeof...(Ts)), void>::type printTuple(tuple<Ts...> tup) { // Print element of tuple cout << get<I>(tup) << " "; // Go to next element printTuple<I + 1>(tup); } // Driver Code int main() { // Creating the tuple tuple<string, string, string> tup("Geeks", "for", "Geeks"); // Function call printTuple(tup); return 0; }
Geeks for Geeks
Este caso se simplifica mucho usando la función constexpr() y las expresiones if constexpr, pero solo están disponibles desde C++17 en adelante. También soy un código simplificado para eso, puede ejecutarlo en C++ 17.
A continuación se muestra la implementación del enfoque anterior:
CPP
// C++ program to iterated thorough // all values. I equals number // of values in tuple #include <iostream> #include <string> #include <tuple> using namespace std; // WARNING: C++17 or above required template <size_t I = 0, typename... Ts> contexpr void printTuple(tuple<Ts...> tup) { // If we have iterated through all elements if constexpr(I == sizeof...(Ts)) { // Last case, if nothing is left to // iterate, then exit the function return; } else { // Print the tuple and go to next element cout << get<I>(tup) << " "; // Going for next element. printTuple<I + 1>(tup); } } // Driver Code int main() { // Initialize the tuple tuple<string, string, string> tup("Geeks", "for", "Geeks"); // Function call printTuple(tup); return 0; }
Salida:
A continuación se muestra la salida del código anterior:
Explicación:
El requisito de std::get() es un índice constante, sin variables. Siempre podemos especificar un número constante para una función de plantilla, «I» aquí es un número constante para la función. Entonces, tendremos n+1 instanciaciones de la función print_num() , donde n es el tamaño de la tupla, cada una tiene “I” como un número constante para sí misma. Entonces, las instancias de estas funciones serán como print_tuple, print_tuple, … e print_tuple, y todas estas funciones se llamarán en secuencia. Esta es la metaprogramación de plantillas
Nota: Por lo tanto, no puede ejecutar el código anterior en el IDE de Geeksforgeeks, debe ejecutarlo en otro compilador. Si desea utilizar C++14 o C++11, puede utilizar el primer método. Las tuplas y las plantillas solo están disponibles en C++ 11, por lo que no se pueden usar versiones anteriores.
Usando Plantillas Variádicas y std::apply() :
- Primero, una guía simple sobre qué es std::get() . std::get() implementa alguna función en elementos de tuplas, considerando elementos de tuplas como valores para esa función. Toma una función f(x, y, z….) y una tupla (x, y, z…) que son argumentos para la función, y devuelve el valor devuelto por f.
- Ahora una cosa más, sobre la expansión variádica, si necesitamos aplicar alguna función en todos los valores de una plantilla variádica, entonces lo hacemos como foo(Ts)…, donde Ts es nuestra plantilla variádica, y foo() es la función que debe aplicarse en todos los valores empaquetados en Ts. Aquí, tres puntos después de la función «…» significa que la función se aplica a la expansión de la plantilla variádica.
- Las funciones Lambda son funciones anónimas, que se pueden declarar y aplicar fácilmente. Se implementan como:
[&a, b, c] (int x, float &y) { // Function Body }
- Aquí x e y son argumentos de la función donde x se pasa por valores e y por referencia. Y, x, y y z son variables que se usarán dentro de la función para algún propósito, por lo que se alimentan a la función, lo que significa que estarán disponibles dentro del alcance de la función.
A continuación se muestra la implementación del mismo:
CPP
// C++ program to iterated thorough // all values. I equals number // of values in tuple #include <iostream> #include <string> #include <tuple> template <typename... Ts> void printTuple(std::tuple<Ts...> tup) { // Getting size of tuple std::size_t length = sizeof...(Ts); // Using std::apply to print elements std::apply( // A lambda function [length](auto const&... ps) { std::cout << "[ "; int k = 0; // Variadic expansion used. ((std::cout << ps << (++k == length ? "" : "; ")), ...); std::cout << " ]"; }, tuple); } // Driver Code int main() { // Initialize the tuple std::tuple<std::string, std::string, std::string> tup("Geeks", "for", "geeks"); // Function call printTuple(tup); return 0; }
- Salida:
A continuación se muestra la salida del código anterior:
Nota: std::apply() solo está disponible desde C++17. Por lo tanto, no puede ejecutar este código en el IDE de Geeksforgeeks, debe ejecutarlo en otro compilador. Si desea utilizar C++14 o C++11, puede utilizar el primer método. Las tuplas y las plantillas solo están disponibles en C++ 11, por lo que no se pueden usar versiones anteriores.
Publicación traducida automáticamente
Artículo escrito por vikram2000b y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA