Die Bibliothek Boost.Tuple stellt eine Klasse boost::tuple
zur Verfügung, die als eine verallgemeinerte Version von std::pair
bezeichnet werden kann. Während std::pair
genau zwei Werte speichert, kann boost::tuple
beliebig viele Werte speichern.
Seit C++11 bietet die Standardbibliothek die Klasse std::tuple
an. Arbeiten Sie in einer C++11-Entwicklungsumgebung, können Sie Boost.Tuple ignorieren, da boost::tuple
und std::tuple
gleich sind.
boost::tuple
als std::pair
-Ersatz#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int> animal;
animal a{"cat", 4};
std::cout << a << '\n';
}
Um die Klasse boost::tuple
verwenden zu können, muss die Headerdatei boost/tuple/tuple.hpp
eingebunden werden. Möchten Sie Variablen vom Typ boost::tuple
von Streams lesen und auf Streams ausgeben, müssen Sie außerdem die Headerdatei boost/tuple/tuple_io.hpp
einbinden. Boost.Tuple stellt keine Master-Headerdatei zur Verfügung, die automatisch alle anderen Headerdateien einbindet.
boost::tuple
wird grundsätzlich genauso verwendet wie std::pair
. So können Sie wie im Beispiel 22.1 zwei Template-Parameter angeben, um zwei Werte zu speichern – in diesem Fall einen vom Typ std::string
und einen vom Typ int
. Die Typdefinition heißt animal
, weil damit der Name und die Anzahl der Beine von Tieren angegeben werden können sollen.
Während die obige Typdefinition von animal
auch mit std::pair
hätte erfolgen können, ist es möglich, Objekte vom Typ boost::tuple
in einen Stream zu schreiben. Dazu muss wie bereits erwähnt die Headerdatei boost/tuple/tuple_io.hpp
eingebunden werden, in der sich die Definitionen der entsprechenden Stream-Operatoren befinden. So gibt Beispiel 22.1 (cat 4)
aus.
boost::tuple
als das bessere std::pair
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int, bool> animal;
animal a{"cat", 4, true};
std::cout << std::boolalpha << a << '\n';
}
Beispiel 22.2 unterstützt zusätzlich zum Namen und zur Anzahl der Beine einen Wahrheitswert, der angibt, ob ein Tier einen Schwanz hat. Alle drei Werte können in einem Tuple untergebracht werden. Wenn Sie das Programm ausführen, wird (cat 4 true)
ausgegeben.
So wie es zu std::pair
eine Hilfsfunktion std::make_pair()
gibt, kann ein Tuple mit Hilfe einer Funktion boost::make_tuple()
erstellt werden. Sehen Sie sich dazu Beispiel 22.3 an.
boost::make_tuple()
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <iostream>
int main()
{
std::cout.setf(std::ios::boolalpha);
std::cout << boost::make_tuple("cat", 4, true) << '\n';
}
Es ist auch möglich, ein Tuple zu erstellen, das Referenzen enthält. Sehen Sie sich dazu Beispiel 22.4 an.
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/ref.hpp>
#include <string>
#include <iostream>
int main()
{
std::string s = "cat";
std::cout.setf(std::ios::boolalpha);
std::cout << boost::make_tuple(boost::ref(s), 4, true) << '\n';
}
Während die Werte 4 und true
als Kopie übergeben und direkt im Tuple gespeichert werden, ist das erste Element eine Referenz auf den String s. Um eine derartige Referenz zu erstellen, wird auf boost::ref()
aus Boost.Ref zugegriffen. Entsprechend muss auf boost::cref()
zugegriffen werden, wenn eine konstante Referenz erstellt werden soll.
Sie dürfen anstatt boost::ref()
std::ref()
aus der C++11-Standardbibliothek verwenden. Im obigen Beispiel muss jedoch boost::ref()
zum Einsatz kommen, weil nur Boost.Ref einen Stream-Operator zur direkten Ausgabe auf die Standardausgabe unterstützt.
Nachdem Sie gesehen haben, wie Tuple erstellt werden, wird im Folgenden auf Elemente eines Tuples zugegriffen. Bei std::pair
geschieht dies über die Eigenschaften first und second. Da ein Tuple jedoch keine festgelegte Anzahl an Elementen besitzt, findet der Zugriff auf eine andere Art und Weise statt.
#include <boost/tuple/tuple.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int, bool> animal;
animal a = boost::make_tuple("cat", 4, true);
std::cout << a.get<0>() << '\n';
std::cout << boost::get<0>(a) << '\n';
}
Es gibt zwei Möglichkeiten, auf ein Element in einem Tuple zuzugreifen: Entweder wird für das Tuple die Methode get()
aufgerufen oder das Tuple als einziger Parameter an eine freistehende Funktion boost::get()
übergeben. In beiden Fällen muss der Index des entsprechenden Elements im Tuple als Template-Parameter übergeben werden. Für Beispiel 22.5 bedeutet das, dass in beiden Fällen auf das erste Element im Tuple a zugegriffen wird und zweimal cat
ausgegeben wird.
Wird ein ungültiger Index angegeben, kompiliert der Code nicht. Die Gültigkeit der Indizes wird zur Kompilierung überprüft, so dass es nicht zu Laufzeitfehlern kommen kann.
Um einen Wert in einem Tuple zu ändern, müssen Sie ebenfalls entweder auf die Methode get()
oder die freistehende Funktion boost::get()
zugreifen.
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int, bool> animal;
animal a = boost::make_tuple("cat", 4, true);
a.get<0>() = "dog";
std::cout << std::boolalpha << a << '\n';
}
Sowohl get()
als auch boost::get()
geben eine Referenz zurück. Im Beispiel 22.6 wird entsprechend der Name geändert und vom Programm (dog 4 true)
ausgegeben.
Boost.Tuple stellt nicht nur überladene Operatoren zur Verfügung, um Tuple auf einen Stream auszugeben oder von einem Stream zu lesen. Boost.Tuple definiert auch Vergleichsoperatoren. Wollen Sie Tuple vergleichen, müssen Sie jedoch mit boost/tuple/tuple_comparison.hpp
eine zusätzliche Headerdatei einbinden.
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string, int, bool> animal;
animal a1 = boost::make_tuple("cat", 4, true);
animal a2 = boost::make_tuple("shark", 0, true);
std::cout << std::boolalpha << (a1 != a2) << '\n';
}
Beispiel 22.7 gibt true
aus, da die beiden Tuple a1 und a2 verschieden sind.
Die Headerdatei boost/tuple/tuple_comparison.hpp
enthält auch Definitionen anderer Vergleichsoperatoren wie operator>
, die einen lexikographischen Vergleich durchführen.
Boost.Tuple unterstützt eine besondere Form von Tuple namens Tier. Ein Tier ist ein Tuple, dessen Elemente alle Referenzen sind. Es kann mit der Funktion boost::tie()
erstellt werden.
boost::tie()
erstellen#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string&, int&, bool&> animal;
std::string name = "cat";
int legs = 4;
bool tail = true;
animal a = boost::tie(name, legs, tail);
name = "dog";
std::cout << std::boolalpha << a << '\n';
}
Im Beispiel 22.8 wird ein Tier a erstellt, das aus Referenzen auf die Variablen name, legs und tail besteht. Indem die Variable name auf einen neuen Wert gesetzt wird, wird gleichzeitig das Tier geändert.
Anstatt boost::tie()
zu verwenden, hätte Beispiel 22.8 auch mit boost::make_tuple()
und boost::ref()
geschrieben werden können. Sehen Sie sich dazu Beispiel 22.9 an.
boost::tie()
erstellen#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <string>
#include <iostream>
int main()
{
typedef boost::tuple<std::string&, int&, bool&> animal;
std::string name = "cat";
int legs = 4;
bool tail = true;
animal a = boost::make_tuple(boost::ref(name), boost::ref(legs),
boost::ref(tail));
name = "dog";
std::cout << std::boolalpha << a << '\n';
}
boost::tie()
verkürzt die Schreibweise. Die Funktion bietet sich auch an, wenn Werte aus einem Tuple entpackt werden soll. Sehen Sie sich dazu Beispiel 22.10 an, in dem eine Funktion ein Tuple zurückgibt und die einzelnen Werte im Tuple sofort in Variablen gespeichert werden.
#include <boost/tuple/tuple.hpp>
#include <string>
#include <iostream>
boost::tuple<std::string, int> new_cat()
{
return boost::make_tuple("cat", 4);
}
int main()
{
std::string name;
int legs;
boost::tie(name, legs) = new_cat();
std::cout << name << ", " << legs << '\n';
}
Mit Hilfe von boost::tie()
werden der String „cat“ und die Zahl 4, die beide zusammen in einem Tuple von new_cat()
zurückgegeben werden, direkt in den Variablen name und legs gespeichert.