Die Bibliothek Boost.PointerContainer bietet für die Verwaltung dynamisch reservierter Objekte spezielle Container an. Verwenden Sie C++11, können Sie einen entsprechenden Container zum Beispiel mit std::vector<std::unique_ptr<int>> selbst erstellen. Die von Boost.PointerContainer angebotenen Container können jedoch zusätzlichen Komfort bieten.
boost::ptr_vector in Aktion#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
int main()
{
boost::ptr_vector<int> v;
v.push_back(new int{1});
v.push_back(new int{2});
std::cout << v.back() << '\n';
}Die Klasse boost::ptr_vector, die im Beispiel 2.1 verwendet wird und in der Headerdatei boost/ptr_container/ptr_vector.hpp definiert ist, funktioniert grundsätzlich genauso wie ein Container vom Typ std::vector<std::unique_ptr<int>>. Da boost::ptr_vector jedoch weiß, dass es dynamisch reservierte Objekte speichert, geben Methoden wie back() eine Referenz auf ein dynamisch reserviertes Objekt zurück und keinen Zeiger. Das Beispiel gibt entsprechend 2 auf die Standardausgabe aus.
boost::ptr_set mit intuitiv richtiger Sortierung#include <boost/ptr_container/ptr_set.hpp>
#include <boost/ptr_container/indirect_fun.hpp>
#include <set>
#include <memory>
#include <functional>
#include <iostream>
int main()
{
boost::ptr_set<int> s;
s.insert(new int{2});
s.insert(new int{1});
std::cout << *s.begin() << '\n';
std::set<std::unique_ptr<int>, boost::indirect_fun<std::less<int>>> v;
v.insert(std::unique_ptr<int>(new int{2}));
v.insert(std::unique_ptr<int>(new int{1}));
std::cout << **v.begin() << '\n';
}Beispiel 2.2 zeigt einen anderen Grund, warum es von Vorteil sein kann, einen spezialisierten Container zu verwenden. In diesem Beispiel werden dynamisch reservierte Variablen vom Typ int in einem boost::ptr_set und in einem std::set gespeichert. Für das std::set wird auf std::unique_ptr zugegriffen.
boost::ptr_set versteht automatisch, dass die Reihenfolge der Elemente von den gespeicherten int-Werten abhängt. std::set hingegen würde std::unique_ptr miteinander vergleichen – also Smartpointer und nicht die Variablen, auf die die Smartpointer zeigen. Damit die Sortierung im Beispiel 2.2 auch bei std::set auf den int-Werten basiert, muss angegeben werden, wie Vergleiche durchzuführen sind. Hierzu wird auf eine Klasse boost::indirect_fun zugegriffen, die aus Boost.PointerContainer stammt. Mit Hilfe dieser Klasse wird std::set mitgeteilt, dass die Sortierung nicht basierend auf den Smartpointern durchgeführt werden soll, sondern basierend auf den int-Variablen, auf die die Smartpointer zeigen. Wenn Sie das Beispiel ausführen, wird zweimal 1 ausgegeben.
Neben boost::ptr_vector und boost::ptr_set stehen weitere Container zur Verfügung, die auf die Verwaltung dynamisch reservierter Objekte spezialisiert sind. Dazu gehören boost::ptr_deque, boost::ptr_list, boost::ptr_map, boost::ptr_unordered_set und boost::ptr_unordered_map. Diese Container entsprechen den aus der Standardbibliothek bekannten Containern.
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/ptr_container/ptr_inserter.hpp>
#include <array>
#include <algorithm>
#include <iostream>
int main()
{
boost::ptr_vector<int> v;
std::array<int, 3> a{{0, 1, 2}};
std::copy(a.begin(), a.end(), boost::ptr_container::ptr_back_inserter(v));
std::cout << v.size() << '\n';
}Boost.PointerContainer bietet für seine Container Inserter an. Diese befinden sich im Namensraum boost::ptr_container und sind in der Headerdatei boost/ptr_container/ptr_inserter.hpp definiert.
Im Beispiel 2.3 wird auf die Funktion boost::ptr_container::ptr_back_inserter() zugegriffen, die einen Inserter vom Typ boost::ptr_container::ptr_back_insert_iterator erstellt. Dieser wird an std::copy() übergeben, um die Zahlen im Array a in den Vektor v zu kopieren. Da v ein Container vom Typ boost::ptr_vector ist, der Adressen von dynamisch reservierten int-Objekten erwartet, muss ein von Boost.PointerContainer angebotener Inserter verwendet werden. Diese erstellen eine Kopie mit new auf dem Heap und fügen die Adresse dem Container hinzu.
Neben boost::ptr_container::ptr_back_inserter() bietet Boost.PointerContainer die Funktionen boost::ptr_container::ptr_front_inserter() und boost::ptr_container::ptr_inserter(), um entsprechende Inserter zu erstellen.
Entwickeln Sie ein Programm, in dem mehrere Instanzen einer Klasse animal mit den Eigenschaften name, legs und has_tail erstellt und in einem Container von Boost.PointerContainer gespeichert werden. Sortieren Sie den Container aufsteigend nach der Anzahl der Beine und schreiben Sie alle Elemente im Container in die Standardausgabe.