Die Boost C++ Bibliotheken

Kapitel 48. Boost.TypeTraits

Typen haben unterschiedliche Eigenschaften, die sich die generische Programmierung zunutze macht. Dazu ist es notwendig, Typen auf Eigenschaften zu überprüfen oder ihre Eigenschaften zu ändern. Boost.TypeTraits ist die Bibliothek, die die dazu erforderlichen Hilfsmittel bietet.

Seit C++11 befindet sich ein Teil der Funktionen, die Boost.TypeTraits anbietet, in der Standardbibliothek. Sie können auf diese Funktionen über die Headerdatei type_traits zugreifen. Boost.TypeTraits bietet jedoch bedeutend mehr Funktionen an als Sie in type_traits vorfinden.

Beispiel 48.1. Typ-Kategorien abfragen
#include <boost/type_traits.hpp>
#include <iostream>

using namespace boost;

int main()
{
  std::cout.setf(std::ios::boolalpha);
  std::cout << is_integral<int>::value << '\n';
  std::cout << is_floating_point<int>::value << '\n';
  std::cout << is_arithmetic<int>::value << '\n';
  std::cout << is_reference<int>::value << '\n';
}

Im Beispiel 48.1 kommen verschiedene Funktionen zum Einsatz, mit denen Typ-Kategorien abgefragt werden können. So wird mit boost::is_integral überprüft, ob ein Typ integral ist – ob er also Ganzzahlen speichern kann. Mit boost::is_floating_point wird überprüft, ob ein Typ Kommazahlen speichern kann. boost::is_arithmetic wird verwendet, um zu überprüfen, ob ein Typ arithmetische Operationen unterstützt. Und boost::is_reference kann verwendet werden, um herauszufinden, ob ein Typ eine Referenz ist.

Beachten Sie, dass sich boost::is_integral und boost::is_floating_point gegenseitig ausschließen. Ein Typ speichert entweder Ganz- oder Kommazahlen. boost::is_arithmetic und boost::is_reference sind hingegen kategorieübergreifend. So werden zum Beispiel arithmetische Operationen sowohl von Ganz- als auch Kommazahlen unterstützt.

Alle Funktionen von Boost.TypeTraits bieten mit value ein Ergebnis an, das entweder true oder false ist. Wenn Sie Beispiel 48.1 ausführen, wird für is_integral<int> und is_arithmetic<int> true und für is_floating_point<int> und is_reference<int> false ausgegeben. Da es sich bei den Funktionen um Templates handelt, findet keine Berechnung zur Laufzeit statt. Das Beispielprogramm verhält sich als wäre true und false in den verschiedenen Zeilen direkt angegeben worden.

Im Beispiel 48.1 war das Ergebnis der verschiedenen Funktionen ein bool-Wert. Dieser konnte direkt auf die Standardausgabe ausgegeben werden. Soll ein Ergebnis von einer Template-Funktion weiterverarbeitet werden, darf es nicht als bool-Wert vorliegen, sondern muss ein Typ sein.

Beispiel 48.2. boost::true_type und boost::false_type
#include <boost/type_traits.hpp>
#include <iostream>

using namespace boost;

int main()
{
  std::cout.setf(std::ios::boolalpha);
  std::cout << is_same<is_integral<int>::type, true_type>::value << '\n';
  std::cout << is_same<is_floating_point<int>::type, false_type>::value <<
    '\n';
  std::cout << is_same<is_arithmetic<int>::type, true_type>::value << '\n';
  std::cout << is_same<is_reference<int>::type, false_type>::value << '\n';
}

Neben value bieten die Funktionen von Boost.TypeTraits das Ergebnis auch in type an. Während value ein bool-Wert ist, ist type ein Typ. So wie es bei value nur zwei Werte gibt – true oder false – gibt es auch bei type nur zwei Ergebnistypen: boost::true_type oder boost::false_type. Dank type ist es möglich, das Ergebnis einer Funktion als Typ an eine andere Funktion zu übergeben.

Im Beispiel 48.2 wird mit boost::is_same eine weitere Funktion von Boost.TypeTraits verwendet. Diese Funktion erwartet zwei Typen als Parameter und überprüft, ob es sich dabei um die gleichen Typen handelt. Um die Ergebnisse von boost::is_integral, boost::is_floating_point, boost::is_arithmetic und boost::is_reference an boost::is_same übergeben zu können, muss auf type zugegriffen werden. type wird daraufhin mit boost::true_type oder boost::false_type verglichen. Die Ergebnisse von boost::is_same werden wiederum über value entgegengenommen. Weil es sich dabei um einen bool-Wert handelt, kann er auf die Standardausgabe ausgegeben werden.

Beispiel 48.3. Mit Boost.TypeTraits Typ-Eigenschaften abfragen
#include <boost/type_traits.hpp>
#include <iostream>

using namespace boost;

int main()
{
  std::cout.setf(std::ios::boolalpha);
  std::cout << has_plus<int>::value << '\n';
  std::cout << has_pre_increment<int>::value << '\n';
  std::cout << has_trivial_copy<int>::value << '\n';
  std::cout << has_virtual_destructor<int>::value << '\n';
}

Beispiel 48.3 stellt einige Funktionen vor, mit denen Eigenschaften von Typen abgefragt werden können. boost::has_plus überprüft, ob ein Typ den Operator operator+ unterstützt und sich somit zwei Objekte des gleichen Typs verknüpfen lassen. boost::has_pre_increment gibt an, ob ein Typ den Prä-Inkrement-Operator operator++ unterstützt. Mit boost::has_trivial_copy kann ermittelt werden, ob ein Typ einen trivialen Copy-Konstruktor hat. Und mit boost::has_virtual_destructor kann überprüft werden, ob ein Typ einen virtuellen Destructor hat.

Wenn Sie Beispiel 48.3 ausführen, wird dreimal true und einmal false ausgegeben.

Beispiel 48.4. Mit Boost.TypeTraits Typ-Eigenschaften ändern
#include <boost/type_traits.hpp>
#include <iostream>

using namespace boost;

int main()
{
  std::cout.setf(std::ios::boolalpha);
  std::cout << is_const<add_const<int>::type>::value << '\n';
  std::cout << is_same<remove_pointer<int*>::type, int>::value << '\n';
  std::cout << is_same<make_unsigned<int>::type, unsigned int>::value <<
    '\n';
  std::cout << is_same<add_rvalue_reference<int>::type, int&&>::value <<
    '\n';
}

Beispiel 48.4 zeigt Ihnen, wie Sie Typ-Eigenschaften ändern. So wird einem Typ zum Beispiel mit boost::add_const ein const hinzugefügt. Ist ein Typ bereits konstant, ändert sich nichts. Der Code kompiliert problemlos, und der Typ bleibt konstant.

boost::remove_pointer entfernt das Sternchen von einem Zeiger und gibt den Typ zurück, auf den der Zeiger zeigt. boost::make_unsigned macht aus einem Typ einen ohne Vorzeichen. Und boost::add_rvalue_reference wandelt einen Typ in eine Rvalue-Referenz um.

Wenn Sie Beispiel 48.4 ausführen, wird viermal true ausgegeben.