La clase std::tuple y sus funciones miembro en C++

Jinku Hu 12 octubre 2023
  1. Utilice la función std::make_tuple para construir objetos std::tuple en C++
  2. Utilice una plantilla de función para imprimir una tupla de cualquier tamaño en C++
La clase std::tuple y sus funciones miembro 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)
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

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