Open Source im professionellen Einsatz
Linux-Magazin 10/2015

Modernes C++ in der Praxis – Folge 24

Containerverwaltung

Container sind nicht nur bei der Virtualisierung derzeit in aller Munde, auch dem Programmierer sind Behälter für Objekte nützlich. Die Version 11 von C++ enthält einige Algorithmen, die die Arbeit mit solchen Containern deutlich vereinfachen.

823

Zu den Methoden, die zwar schon eine Weile zu C++ gehören, nun aber neu in den Standard aufgenommen werden sollen, gehören etwa »std::any_of()« , »std::all_of()« und »std::none_of()« . Sie evaluieren alle Elemente eines Containers in einem Schritt. Auch die verschiedenen Varianten der »emplace()« -Methode, die Elemente eines Containers direkt in ihm erzeugt, gehören dazu. Und schließlich geht es um die Methode »shrink_to_fit()« für sequenzielle Container wie den »std::vector« . Mit dieser Methode lässt sich ein Vektor auf seine wahre Größe reduzieren.

Blick in die Zukunft

Die drei Funktionen »std::any_of()« , »std::all_of()« und »std::none_of()« benötigen einen Bereich und ein Prädikat. Sie ermitteln, ob mindestens eines, alle oder keines der Elemente eines Bereiches ein bestimmtes Prädikat erfüllen. Unter einem Prädikat versteht man dabei eine Funktion, die für jedes Argument den Wert »true« oder »false« zurückgibt. Listing 1 zeigt die drei praktischen Funktionen in der Anwendung.

Listing 1

Anwendungsbeispiel für Funktionen

01 #include <algorithm>
02 #include <iostream>
03 #include <vector>
04
05 int main(){
06
07  std::cout << std::boolalpha << std::endl;
08
09  auto even= [](int i){ return i%2 == 0 ;};
10
11  std::vector<int> myVec{1,2,3,4,5,6,7,8,9};
12
13  std::cout << "std::any_of(myVec.begin(),myVec.end(),even): " << std::any_of(myVec.begin(),myVec.end(),even) << std::endl;
14  std::cout << "std::all_of(myVec.begin(),myVec.end(),even): " << std::all_of(myVec.begin(),myVec.end(),even) << std::endl;
15  std::cout << "std::none_of(myVec.begin(),myVec.end(),even: " << std::none_of(myVec.begin(),myVec.end(),even) << std::endl;
16
17  std::cout << std::endl;
18
19 }

Das kleine Programm enthält nicht viel Überraschungspotenzial. Die drei Funktionen benötigen die Headerdatei »algorithm« in Zeile 1. Als Prädikat kommt die Lambda-Funktion (Zeile 9) zum Einsatz. Sie ermittelt, ob ihr Argument eine gerade Zahl ist. Abbildung 1 zeigt die Ausgabe des Programms.

Abbildung 1: std::any_of(), std::all_of() und std::none_of() auf einen std::vector angewandt.

Ein genauer Blick in die Onlinedokumentation der drei Funktionen [1] lohnt sich. Die Bereiche, auf denen die Funktionen agieren, werden durch Input-Iteratoren definiert. Zudem muss die Funktion ein Prädikat sein. So steht es in dem Abschnitt "Type Requirements" der Onlinedokumentation. Dabei stellen sowohl Input-Iterator [2] als auch Predicat [3] ein so genanntes Concept [4] dar.

Mit Konzept

Ein Concept definiert eine verbindliche Bedingung für einen Typparameter eines Template. Concepts sind den Typklassen in Haskell sehr ähnlich. Auch der nächste Standard C++17 wird mit großer Wahrscheinlichkeit Concepts erhalten. Diese heißen umgangssprachlich meist Concepts Lite und besitzen zwei große Vorteile. Zum einen beschreiben sie in der Template-Deklaration eindeutig die Bedingungen, die die Typparameter zu erfüllen haben, zum anderen erzeugt der Compiler nun gut leserliche Fehlermeldungen, falls die Bedingungen durch die Typparameter nicht erfüllt werden. Insbesondere für die viele Seiten langen Fehlermeldungen, die der Programmierer früher heraufbeschwor, wenn er ein Template mit unpassenden Template-Parametern verwendete, war C++ leider legendär.

Im konkreten Fall benötigen die Funktionen einen Input-Iterator. Das ist ein Iterator, der nur in eine Richtung vorwärtsschreiten und dabei jedes Element nur einmal lesen kann. Diese Eigenschaft erfüllen die Container der Standard Template Library und selbst ein Dateistream. Daher ist zugesichert, dass sich die drei Funktionen auch auf einem assoziativen Container wie »std::unordered_map« anwenden lassen (Listing 2).

Listing 2

Anwendung auf std::unordered_map

01 #include <algorithm>
02 #include <iostream>
03 #include <string>
04 #include <unordered_map>
05
06 int main(){
07
08  std::cout << std::boolalpha << std::endl;
09
10  auto even= [](std::pair<int,std::string> p ){ return p.first % 2 == 0;};
11
12  std::unordered_map<int,std::string> myUnordMap{{1,"one"},{2,"two"},{3,"three"},{4,"four"},{5,"five"}};
13
14  std::cout << "std::any_of(myUnordMap.begin(),myUnordMap.end(),even): " << std::any_of(myUnordMap.begin(),myUnordMap.end(),even) << std::endl;
15  std::cout << "std::all_of(myUnordMap.begin(),myUnordMap.end(),even): " << std::all_of(myUnordMap.begin(),myUnordMap.end(),even) << std::endl;
16  std::cout << "std::none_of(myUnordMap.begin(),myUnordMap.end(),even: " << std::none_of(myUnordMap.begin(),myUnordMap.end(),even) << std::endl;
17  std::cout << std::endl;
18
19 }

Die Lambda-Funktion »even()« in Zeile 10 ermittelt für alle Paare »p« der »std::unordered_map« , ob deren Schlüssel »p.first« gerade sind. Die Antwort gibt die Ausgabe des Programms, sie fällt ähnlich aus, wie schon bei Listing 1 und in Abbildung 1 zu sehen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • C++11

    In C++11 lässt sich manches prägnanter formulieren als in klassischem C++. Dieser Artikel zeigt, wie die neue Range-basierte For-Schleife und die automatische Typableitung dabei helfen.

  • C++11

    "Performance matters": Was sich wie ein Glaubensbekenntnis anhört, bleibt ein wichtiges Designkriterium in C++. Mit den neuen Hashtabellen kann der Programmierer richtig Tempo machen.

  • C++11

    Die Referenz-Wrapper bilden eine kleine, aber feine neue Bibliothek in C++11. Diese Objekte verhalten sich wie Referenzen, der Artikel erklärt die Details.

  • C++11

    Die Usability von C++ als objektorientierte Sprache lebt davon, wie einfach es ist, neue Objekte zu erzeugen. Kein Wunder, dass C++11 gegenüber früheren Versionen diesen Baugrund besser erschlossen hat.

  • C++11

    Lambda-Funktionen sind die praktischen Helfer der Sprache C++11. Schon nach kurzer Zeit möchte kein C++-Entwickler sie missen, denn mit ihnen ist ein Algorithmus rasch und ohne Umschweife formuliert. Außerdem darf er sie wie Objekte behandeln.

comments powered by Disqus

Ausgabe 10/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.