Die Boost C++ Bibliotheken

Algorithmen

Sie können sich eine Range als zwei Iteratoren vorstellen, die auf den Anfang und das Ende einer Gruppe an Elementen zeigen, über die iteriert werden kann. Da alle Container Iteratoren unterstützen, kann jeder Container als Range dargestellt werden. Da alle Algorithmen von Boost.Range als ersten Parameter eine Range erwarten, können Sie einen Container wie std::vector direkt übergeben. Sie müssen also nicht erst begin() und end() aufrufen, um zwei Iteratoren einzeln zu übergeben. So sind Sie davor geschützt, versehentlich den Start- und End-Iterator in der falschen Reihenfolge oder Iteratoren zu übergeben, die zu zwei verschiedenen Containern gehören.

Beispiel 30.1. Zählen mit boost::count()
#include <boost/range/algorithm.hpp>
#include <array>
#include <iostream>

int main()
{
  std::array<int, 6> a{{0, 1, 0, 1, 0, 1}};
  std::cout << boost::count(a, 0) << '\n';
}

Im Beispiel 30.1 wird der Algorithmus boost::count() verwendet. Dazu wurde die Headerdatei boost/range/algorithm.hpp eingebunden. Über diese Headerdatei erhalten Sie Zugriff auf alle Algorithmen, für die es ein Gegenstück in der Headerdatei algorithm in der Standardbibliothek gibt.

Wie bei allen von Boost.Range angebotenen Algorithmen muss als erster Parameter eine Range übergeben werden. Da Container auch Ranges sind, kann ein Objekt vom Typ std::array direkt an boost::count() übergeben werden. Da boost::count() das Gleiche macht wie std::count(), muss außerdem ein Wert übergeben werden, mit dem die Elemente in der Range verglichen werden sollen.

Wenn Sie Beispiel 30.1 ausführen, wird 3 auf die Standardausgabe ausgegeben, da a drei Nullen enthält.

Beispiel 30.2 stellt weitere Algorithmen vor, die wie boost::count() Algorithmen aus der Standardbibliothek ähneln.

Beispiel 30.2. Mit der Standardbibliothek verwandte Range-Algorithmen
#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>
#include <array>
#include <iterator>
#include <iostream>

int main()
{
  std::array<int, 6> a{{0, 1, 2, 3, 4, 5}};
  boost::random_shuffle(a);
  boost::copy(a, std::ostream_iterator<int>{std::cout, ","});
  std::cout << "\n" << *boost::max_element(a) << '\n';
  std::cout << boost::accumulate(a, 0) << '\n';
}

boost::random_shuffle() macht das Gleiche wie std::random_shuffle() und ändert die Reihenfolge der Elemente in der Range nach dem Zufallsprinzip. Im Beispiel 30.2 verwendet boost::random_shuffle() einen Standardzufallsgenerator. Sie können der Funktion jedoch auch als zweiten Parameter einen Zufallsgenerator übergeben, wie sie in C++11 in der Headerdatei random oder von Boost.Random zur Verfügung gestellt werden.

boost::copy() macht das Gleiche wie std::copy(). Auch boost::max_element() und boost::accumulate() unterscheiden sich nicht von den gleichnamigen Algorithmen aus der Standardbibliothek. boost::max_element() gibt so wie std::max_element() einen Iterator auf das Element mit der größten Zahl zurück.

Beachten Sie, dass für boost::accumulate() die Headerdatei boost/range/numeric.hpp eingebunden werden muss. So wie std::accumulate() in numeric definiert ist, ist auch boost::accumulate() in boost/range/numeric.hpp und nicht in boost/range/algorithm.hpp definiert.

Boost.Range bietet einige Algorithmen an, für die es kein Gegenstück in der Standardbibliothek gibt.

Beispiel 30.3. Range-Algorithmen ohne Gegenstück in der Standardbibliothek
#include <boost/range/algorithm_ext.hpp>
#include <array>
#include <deque>
#include <iterator>
#include <iostream>

int main()
{
  std::array<int, 6> a{{0, 1, 2, 3, 4, 5}};
  std::cout << std::boolalpha << boost::is_sorted(a) << '\n';
  std::deque<int> d;
  boost::push_back(d, a);
  boost::remove_erase(d, 2);
  boost::copy_n(d, 3, std::ostream_iterator<int>{std::cout, ","});
}

Um die im Beispiel 30.3 vorgestellten Algorithmen verwenden zu können, müssen Sie die Headerdatei boost/range/algorithm_ext.hpp einbinden. Über diese Headerdatei erhalten Sie Zugriff auf Algorithmen, für die es kein Gegenstück in der Standardbibliothek gibt.

boost::is_sorted() gibt an, ob die Werte in einer Range aufsteigend sortiert sind. Da dies im Beispiel 30.3 für a der Fall ist, gibt boost::is_sorted() true zurück. Sie können boost::is_sorted() auch ein Prädikat als zweiten Parameter übergeben, wenn Sie zum Beispiel auf absteigende Sortierung überprüfen wollen.

boost::push_back() erwartet als ersten Parameter einen Container und als zweiten Parameter eine Range. Der Container muss die Methode push_back() anbieten. Alle Werte in der Range werden über diese Methode dem Container hinzugefügt – in der Reihenfolge, in der sie in der Range vorliegen. Da d anfangs leer ist, speichert d nach dem Aufruf von boost::push_back() die gleichen Zahlen in der gleichen Reihenfolge wie a.

boost::remove_erase() entfernt die Zahl 2 aus d. Dieser Algorithmus ist insofern nützlich, als dass er einen Aufruf von std::remove() und der Methode erase() für den entsprechenden Container vereint. Sie müssen dank boost::remove_erase() nicht selbst zuerst den Iterator finden, der auf das entsprechende Element zeigt, um in einem zweiten Schritt den Iterator an erase() zu übergeben.

boost::copy_n() ist gleichbedeutend mit boost::copy(), erwartet als zweiten Parameter aber eine Angabe, wie viele Elemente aus der Range kopiert werden sollen. Im Beispiel 30.3 werden demnach lediglich die ersten drei Zahlen aus d auf die Standardausgabe ausgegeben. Da in der vorherigen Zeile die Zahl 2 aus d entfernt wurde, wird 0,1,3, ausgegeben, wenn Sie das Programm ausführen.