Die Klasse std::tuple und ihre Memberfunktionen in C++

Jinku Hu 12 Oktober 2023
  1. Verwenden Sie die Funktion std::make_tuple, um std::tuple-Objekte in C++ zu konstruieren
  2. Verwenden einer Funktionsvorlage zum Drucken eines Tupels beliebiger Größe in C++
Die Klasse std::tuple und ihre Memberfunktionen in C++

Dieser Artikel demonstriert mehrere Methoden zur Verwendung der Klasse std::tuple und ihrer Memberfunktionen in C++.

Verwenden Sie die Funktion std::make_tuple, um std::tuple-Objekte in C++ zu konstruieren

Die Funktion std::tuple ist die STL-Klassenvorlage, die eine Sammlung von heterogenen Typen fester Größe implementiert. Im Allgemeinen werden Tupel in der Mathematik häufig verwendet, um die endliche Folge von Elementen zu bezeichnen, aber es wird auch in Programmiersprachen mit dem Produkt verschiedener Typen in Verbindung gebracht.

In C++ gibt es eine ähnliche Klasse, std::pair, die nur zwei heterogene Objekte speichern kann. Die Objektdeklaration std::tuple gibt normalerweise die Typen an, aus denen das Tupel besteht, und die Reihenfolge, in der auf sie zugegriffen wird. Diese Typen werden ähnlich wie std::pair als Template-Parameter angegeben. Der Befehl std::tuple kann mit verschiedenen Konstruktoren initialisiert werden. Trotzdem verwenden wir in diesem Fall die Funktion std::make_tuple. Der Prozess std::make_tuple nimmt eine variable Anzahl von Argumenten und versucht, die Typen automatisch abzuleiten. Die Funktion gibt das std::tuple-Objekt zurück, das die angegebenen Werte enthält.

Im folgenden Beispielprogramm implementieren wir eine Funktion namens printTupleOfThree, die das Tupel von drei Werten ausgibt. Beachten Sie, dass diese Vorlagenfunktion die Tupel mit einer anderen Anzahl von Elementen nicht drucken kann. Der Befehl printTupleOfThree kann bei Tupeln mit mehr als drei Elementen aufgerufen werden, gibt aber nur die ersten drei aus. Da es also ineffizient wäre, überladene Funktionen für Tupel unterschiedlicher Größe zu definieren, müssen wir das Problem mit einem anderen Ansatz lösen.

#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;
}

Ausgabe:

(one, two, 1)
(one, two, 2)

Verwenden einer Funktionsvorlage zum Drucken eines Tupels beliebiger Größe in C++

Die Lösung des im vorherigen Abschnitt angesprochenen Problems heißt variadische Vorlagen. Letzteres ist die Eigenschaft von Vorlagen, eine variable Anzahl von Argumenten zu akzeptieren. Beachten Sie, dass printTuple eine variadische Vorlagenfunktion ist, die die Member-Funktion print der Klasse TuplePrinter aufruft. Letzteres ist ein Klassen-Template, das eine einzelne Member-Funktion namens print definiert, aber denken Sie daran, dass es zwei Definitionen der TuplePrinter-Klasse gibt. Diese Implementierung wird als rekursive Template-Instanziierung bezeichnet und ist eine bekannte Technik in der Template-basierten Metaprogrammierung.

Die Metaprogrammierung beinhaltet Methoden, um Polymorphismus zur Kompilierzeit zu nutzen, und es ist ein weitaus umfassenderes Thema, als dieser Artikel behandeln kann. Es wäre am besten, wenn Sie in einem Buch mit dem Titel C++ Templates - The Complete Guide nachschlagen, um einen detaillierten Überblick über die Funktionen von Templates und Metaprogrammierungstechniken zu erhalten, die diese verwenden. Als Ergebnis erhalten wir, dass die Funktion printTuple mit Tupel-Objekten unterschiedlicher Größe kompatibel ist und alle ihre Mitglieder in den cout-Stream drucken können.

#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;
}

Ausgabe:

(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