La clase std::tuple y sus funciones miembro en C++
-
Utilice la función
std::make_tuple
para construir objetosstd::tuple
en C++ - Utilice una plantilla de función para imprimir una tupla de cualquier tamaño en C++
Este artículo demostrará varios métodos para usar la clase std::tuple
y sus funciones miembro en C++.
Utilice la función std::make_tuple
para construir objetos std::tuple
en C++
La función std::tuple
es la plantilla de clase STL que implementa una colección de tipos heterogéneos de tamaño fijo. Generalmente, las tuplas se utilizan con frecuencia en matemáticas para denotar la secuencia finita de elementos, pero también están asociadas con el producto de diferentes tipos en lenguajes de programación.
En C++, existe una clase similar, std::pair
, que puede almacenar solo dos objetos heterogéneos. La declaración del objeto std::tuple
generalmente especifica los tipos de los que consistirá la tupla y el orden en que se accederá a ellos. Estos tipos se especifican como parámetros de plantilla similares a std::pair
. El comando std::tuple
se puede inicializar con diferentes constructores. Aún así, en este caso, utilizamos la función std::make_tuple
. El proceso std::make_tuple
toma un número variable de argumentos e intenta deducir los tipos automáticamente. La función devuelve el objeto std::tuple
que contiene los valores dados.
En el siguiente programa de ejemplo, implementamos una función llamada printTupleOfThree
, que imprime la tupla de tres valores. Tenga en cuenta que esta función de plantilla no puede imprimir las tuplas con un número diferente de elementos. El comando printTupleOfThree
se puede llamar en tuplas con más de tres elementos, pero solo generará los tres primeros. Entonces, dado que sería ineficiente definir funciones sobrecargadas para tuplas de diferentes tamaños, debemos resolver el problema utilizando un enfoque diferente.
#include <iostream>
#include <tuple>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::tuple;
using std::vector;
template <typename Tuple>
void printTupleOfThree(Tuple t) {
cout << "(" << std::get<0>(t) << ", " << std::get<1>(t) << ", "
<< std::get<2>(t) << ")" << endl;
}
int main() {
std::vector<string> v1{"one", "two", "three", "four", "five", "six"};
std::vector<int> v2 = {1, 2, 3, 4, 5, 6};
std::vector<float> v3 = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
auto t1 = std::make_tuple(v1[0], v1[1], v2[0]);
auto t2 = std::make_tuple(v1[0], v1[1], v2[0], v3[0], v3[1]);
printTupleOfThree(t1);
printTupleOfThree(t2);
return EXIT_SUCCESS;
}
Producción :
(one, two, 1)
(one, two, 2)
Utilice una plantilla de función para imprimir una tupla de cualquier tamaño en C++
La solución al problema planteado en la sección anterior se llama plantillas variadas. Esta última es la característica de las plantillas para aceptar un número variable de argumentos. Tenga en cuenta que printTuple
es una función de plantilla variable que llama a la función miembro print
de la clase TuplePrinter
. Esta última es una plantilla de clase que define una función de un solo miembro llamada print
, pero recuerde que hay dos definiciones de la clase TuplePrinter
. Esta implementación se denomina instanciación de plantilla recursiva y es una técnica conocida en la metaprogramación basada en plantillas.
La metaprogramación implica métodos para utilizar el polimorfismo en tiempo de compilación, y es un tema mucho más amplio de lo que este artículo puede manejar. Lo mejor sería consultar un libro llamado C++ Templates - The Complete Guide para obtener una descripción detallada de las características de las plantillas y las técnicas de metaprogramación que las utilizan. Como resultado, obtenemos que la función printTuple
sea compatible con objetos de tupla de diferentes tamaños y pueda imprimir todos sus miembros en la secuencia cout
.
#include <iostream>
#include <tuple>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::tuple;
using std::vector;
template <class Tuple, std::size_t N>
struct TuplePrinter {
static void print(const Tuple& t) {
TuplePrinter<Tuple, N - 1>::print(t);
std::cout << ", " << std::get<N - 1>(t);
}
};
template <class Tuple>
struct TuplePrinter<Tuple, 1> {
static void print(const Tuple& t) { std::cout << std::get<0>(t); }
};
template <class... Args>
void printTuple(const std::tuple<Args...>& t) {
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")" << endl;
}
int main() {
std::vector<string> v1{"one", "two", "three", "four", "five", "six"};
std::vector<int> v2 = {1, 2, 3, 4, 5, 6};
std::vector<float> v3 = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
auto t1 = std::make_tuple(v1[0], v1[1], v3[0]);
auto t2 = std::make_tuple(v1[0], v1[1], v2[1], v3[0], v3[1]);
printTuple(t1);
printTuple(t2);
return EXIT_SUCCESS;
}
Producción :
(one, two, 1.1)
(one, two, 2, 1.1, 2.2)
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook