Die Boost C++ Bibliotheken

Hilfsklassen und -funktionen

Die von Boost.Range angebotenen Algorithmen und Adapter basieren auf Templates. Sie müssen einen Container nicht explizit in eine Range umwandeln, um ihn an einen Algorithmus oder Adapter übergeben zu können. Boost.Range definiert jedoch auch einige Range-Klassen, von denen die wichtigste boost::iterator_range ist. boost::iterator_range wird benötigt, weil Adapter und einige Algorithmen Ranges zurückgeben und diese einen Typ haben müssen. Außerdem gibt es einige Hilfsfunktionen, um Ranges zu erstellen, deren Iteratoren alle für eine Iteration notwendigen Informationen besitzen. Diese Ranges zeigen über ihre Iteratoren auf keine Container oder andere Datenstrukturen. Auch hier kommt eine Klasse wie boost::iterator_range zum Einsatz.

Beispiel 30.7. Mit boost::irange() eine Range für Ganzzahlen erstellen
#include <boost/range/algorithm.hpp>
#include <boost/range/irange.hpp>
#include <iostream>

int main()
{
  boost::integer_range<int> ir = boost::irange(0, 3);
  boost::copy(ir, std::ostream_iterator<int>{std::cout, ","});
}

Im Beispiel 30.7 kommt die Funktion boost::irange() zum Einsatz. Diese Funktion erstellt eine Range für Ganzzahlen, ohne dass ein Container oder eine andere Datenstruktur verwendet werden muss. Sie übergeben der Funktion lediglich eine Unter- und Obergrenze, wobei die Obergrenze gerade nicht mehr zur Range gehört.

boost::irange() gibt eine Range vom Typ boost::integer_range zurück. Diese Klasse ist von boost::iterator_range abgeleitet. boost::iterator_range ist ein Template, das als Parameter einen Iteratortyp erwartet. Der Iterator, der von boost::irange() verwendet wird, hängt eng mit dieser Funktion zusammen und ist ein Implementationsdetail. Um die Handhabung zu vereinfachen, steht boost::integer_range zur Verfügung. Diesem Template muss lediglich ein Typ für Ganzzahlen übergeben werden.

Wenn Sie Beispiel 30.7 ausführen, wird Ihnen 0,1,2 ausgegeben.

Beispiel 30.8. Mit boost::istream_range() eine Range für einen Inputstream erstellen
#include <boost/range/algorithm.hpp>
#include <boost/range/istream_range.hpp>
#include <iterator>
#include <iostream>

int main()
{
  boost::iterator_range<std::istream_iterator<int>> ir =
    boost::istream_range<int>(std::cin);
  boost::copy(ir, std::ostream_iterator<int>{std::cout, "\n"});
}

Beispiel 30.8 stellt Ihnen die Funktion boost::istream_range() vor, mit der Sie eine Range für einen Inputstream erstellen können. Diese Funktion gibt die Range als boost::iterator_range zurück. Das bedeutet, Sie müssen den Iteratortyp als Template-Parameter angeben.

Wenn Sie Beispiel 30.8 ausführen, eine Zahl eingeben und anschließend Enter drücken, wird die Zahl in der nächsten Zeile ausgegeben. Geben Sie erneut eine Zahl ein und drücken Enter, wird auch diese ausgegeben. Die Range, die boost::istream_range() zurückgibt, erlaubt es boost::copy(), über die eingegebenen Zahlen zu iterieren und sie auf std::cout auszugeben.

Sie können das Programm jederzeit mit Strg+C beenden.

Neben boost::iterator_range bietet Boost.Range auch eine Klasse boost::sub_range an. Diese Klasse ist von boost::iterator_range abgeleitet. So wie bei boost::iterator_range handelt es sich auch bei boost::sub_range um ein Template. boost::sub_range erwartet jedoch einen Rangetyp als Template-Parameter und keinen Iteratortyp. Das kann die Handhabung etwas vereinfachen. Sehen Sie sich dazu Beispiel 30.9 an.

Beispiel 30.9. Mit boost::sub_range() Ranges einfacher erstellen
#include <boost/range/algorithm.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/sub_range.hpp>
#include <array>
#include <iterator>
#include <iostream>

int main()
{
  std::array<int, 6> a{{0, 1, 2, 3, 4, 5}};
  boost::iterator_range<std::array<int, 6>::iterator> r1 =
    boost::random_shuffle(a);
  boost::sub_range<std::array<int, 6>> r2 =
    boost::random_shuffle(r1);
  boost::copy(r2, std::ostream_iterator<int>{std::cout, ","});
}

Einige von Boost.Range angebotene Algorithmen geben eine Range zurück – so zum Beispiel boost::random_shuffle(). Auch wenn dieser Algorithmus die Range, die als Parameter übergeben wird, direkt verändert, gibt er zusätzlich einen Verweis auf diese Range zurück.

Im Beispiel 30.9 wird boost::random_shuffle() zweimal aufgerufen und jedes Mal der Rückgabewert explizit gespeichert. Beim ersten Mal wird boost::iterator_range verwendet, beim zweiten Mal boost::sub_range. Beide Klassen unterscheiden sich lediglich im Template-Parameter. boost::sub_range hat nicht nur den Vorteil, dass die Klasse üblicherweise einfach zu instanziieren ist. Eine Range vom Typ boost::sub_range kennt auch einen Typ const_iterator, weil diese Klasse mit einer Range und nicht mit einem Iterator instanziiert wird.