Die Boost C++ Bibliotheken

Kapitel 70. Boost.Assign

Die Bibliothek Boost.Assign bietet Hilfsfunktionen an, um Container zu initialisieren oder Elemente Containern hinzuzufügen. Die Funktionen sind besonders hilfreich, wenn sehr viele Elemente in einem Container gespeichert werden sollen. So ist es dank der von Boost.Assign angebotenen Funktionen nicht notwendig, selbst wiederholt eine Methode wie push_back() aufzurufen und Elemente einzeln in einem Container ablegen zu müssen.

Arbeiten Sie in einer Entwicklungsumgebung, die C++11 unterstützt, profitieren Sie von Initialisierungslisten. So können Sie dem Konstruktor von Containern üblicherweise beliebig viele Werte übergeben, mit denen Container initialisiert werden. Dank Initialisierungslisten sind Sie in C++11 nicht auf Boost.Assign angewiesen. Boost.Assign bietet jedoch auch Hilfsfunktionen an, um einem existierenden Container mehrere Werte hinzufügen zu können. Diese Hilfsfunktionen können auch in einer C++11-Entwicklungsumgebung nützlich sein.

Im Beispiel 70.1 werden einige Funktionen vorgestellt, mit denen Container initialisiert werden können. Es reicht, die Headerdatei boost/assign.hpp einzubinden, um Zugriff auf sämtliche von Boost.Assign definierten Funktionen zu haben.

Beispiel 70.1. Container initialisieren
#include <boost/assign.hpp>
#include <boost/tuple/tuple.hpp>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <utility>

using namespace boost::assign;

int main()
{
  std::vector<int> v = list_of(1)(2)(3);

  std::stack<int> s = list_of(1)(2)(3).to_adapter();

  std::vector<std::pair<std::string, int>> v2 =
    list_of<std::pair<std::string, int>>("a", 1)("b", 2)("c", 3);

  std::map<std::string, int> m =
    map_list_of("a", 1)("b", 2)("c", 3);

  std::vector<boost::tuple<std::string, int, double>> v3 =
    tuple_list_of("a", 1, 9.9)("b", 2, 8.8)("c", 3, 7.7);
}

Boost.Assign bietet drei Funktionen an, um Container zu initialisieren. Die wichtigste dieser drei Funktionen ist boost::assign::list_of() – mit dieser Funktion arbeiten Sie grundsätzlich. boost::assign::map_list_of() verwenden Sie, wenn Sie auf std::map zugreifen. boost::assign::tuple_list_of() wiederum setzen Sie ein, wenn Sie Tuple in einem Container initialisieren möchten.

Sie müssen nicht auf boost::assign::map_list_of() oder boost::assign::tuple_list_of() zugreifen. Sie können alle Container mit boost::assign::list_of() initialisieren. Greifen Sie jedoch auf std::map oder einen Container mit Tuplen zu, müssen Sie bei boost::assign::list_of() einen Template-Parameter angeben, um der Funktion mitzuteilen, wie Werte im Container gespeichert werden. Dieser Template-Parameter entfällt bei boost::assign::map_list_of() und boost::assign::tuple_list_of().

Allen drei Funktionen ist gemein, dass sie ein Proxy-Objekt zurückgeben. Das Objekt, das von boost::assign::list_of() und den anderen beiden Funktionen zurückgegeben wird, überlädt den Operator operator(). Sie können diesen Operator mehrfach aufrufen, um Werte im Container zu speichern. Obwohl Sie dabei auf ein anderes Objekt und nicht auf den Container zugreifen, ändern Sie durch den Proxy den Container.

Wenn Sie Adapter wie std::stack initialisieren möchten, müssen Sie für den Proxy die Methode to_adapter() aufrufen. Der Proxy greift dann auf die Methode push() zu, die von allen Adaptern angeboten wird.

Beachten Sie, dass boost::assign::tuple_list_of() ausschließlich Tuple vom Typ boost::tuple unterstützt. Sie können die Funktion nicht verwenden, um Container mit Tuplen aus der Standardbibliothek zu initialisieren.

Beispiel 70.2. Containern Werte hinzufügen
#include <boost/assign.hpp>
#include <vector>
#include <deque>
#include <set>
#include <queue>

int main()
{
  std::vector<int> v;
  boost::assign::push_back(v)(1)(2)(3);

  std::deque<int> d;
  boost::assign::push_front(d)(1)(2)(3);

  std::set<int> s;
  boost::assign::insert(s)(1)(2)(3);

  std::queue<int> q;
  boost::assign::push(q)(1)(2)(3);
}

Boost.Assign bietet mit boost::assign::push_back(), boost::assign::push_front(), boost::assign::insert() und boost::assign::push() weitere Funktionen an, die einen Proxy zurückgeben. Sie müssen diesen Funktionen den Container übergeben, dem Sie neue Elemente hinzufügen möchten. Sie greifen dann wie zuvor über den Operator operator() auf den Proxy zu und geben die Werte an, die Sie im Container speichern möchten.

Die vier Funktionen boost::assign::push_back(), boost::assign::push_front(), boost::assign::insert() und boost::assign::push() heißen so, weil die von ihnen zurückgegebenen Proxys die gleichnamigen Methoden für den Container aufrufen. So werden im Beispiel 70.2 die drei Zahlen 1, 2 und 3 dem Vektor v über den Aufruf von push_back() hinzugefügt.

Boost.Assign bietet weitere Funktionen an, um einem Container Werte hinzuzufügen. So können Sie zum Beispiel boost::assign::add_edge() verwenden, um einen Proxy für Graphen von Boost.Graph zu erhalten.

Aufgabe

Überarbeiten Sie dieses Programm mit Hilfe von Boost.Assign:

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout));
    v.push_back(4);
    v.push_back(5);
    v.push_back(6);
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout));
}