Die Klasse std::tuple und ihre Memberfunktionen in C++
-
Verwenden Sie die Funktion
std::make_tuple
, umstd::tuple
-Objekte in C++ zu konstruieren - Verwenden einer Funktionsvorlage zum Drucken eines Tupels beliebiger Größe 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)
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