Open Source im professionellen Einsatz
Linux-Magazin 10/2016

Modernes C++ in der Praxis – Folge 30

Bibliotheks-Karriere

Die wichtigsten Neuerungen im neuen C++17-Standard finden in den Bibliotheken statt: der leichtgewichtige String-Wrapper "string_view", die parallelisierten Algorithmen der STL, die Dateisystem-Bibliothek oder die praktischen Datentypen "std::optional" und "std::any".

968

Bevor dieser Artikel die Neuerungen der C++17-Bibliotheken würdigt, kommt er auf eine offene Hausaufgabe zu sprechen. Der vorige Artikel [1] schloss nämlich mit der Frage, was das Programm

int main()??<
  ??(??)??<??>();
??>

macht. Es setzt Trigraphen [2] ein. Das sind Kombinationen aus drei Buchstaben, die für ein Zeichen stehen. Trigraphen waren notwendig, wenn sich das gewünschte Zeichen nicht per Tastatur eintippen lässt. C++17 bricht mit diesem Erbe von C und erklärt die Zeichenkombinationen »??<« für »{« , »??>« für »}« , »??(« für »[« und »??)« für »]« als nicht mehr zulässig. Schon ein wenig Suchen und Ersetzen löst das Rätsel:

int main(){
  []{}();
}

Löst es fast – denn wofür steht der dadaistische Ausdruck »[]{}()« ? Er ist eine Lambda-Funktion, die »[]« einleitet, die einen leeren Funktionskörper »{}« besitzt und die »()« an Ort und Stelle aufruft. Das ist die Art Humor, über den C++-Entwickler lachen. Kommen wir aber nun zu etwas völlig anderem.

Die "std::string_view"-View

Eine »std:.string_view« [3] ist eine Referenz auf einen String, die den String nicht besitzt. Das klingt komplizierter, als es ist. »std::string_view« repräsentiert eine View (Referenz) auf eine Sequenz von Buchstaben. Das kann ein C++- oder C-String sein. C++17 bietet wie immer vier Typ-Synonyme für jeden zugrunde liegenden Zeichentyp an (Tabelle 1).

Tabelle 1

Typ-Synonyme

Type

Definition

std::string_view

std::basic_string_view<char>

std::wstring_view

std::basic_string_view<wchar_t>

std::u16string_view

std::basic_string_view<char16_t>

std::u32string_view

std::basic_string_view<char32_t>

Warum ist der Bedarf so groß nach der View, dass Google, LLVM und Bloomberg mit »std::string_view« schon selbst etwas Ähnliches implementiert hatten? Es lässt sich billig kopieren, da die View typischerweise nur zwei Informationen enthält: den Zeiger auf die Zeichensequenz und deren Länge.

Um den Umstieg von »std::string« zu »std::string_view« zu erleichtern – das gilt natürlich für die weiteren Typ-Synonyme gleichermaßen –, bietet »std::string_view« ein ähnliches Interface wie »std::string« an, das aus kaum mehr besteht als den lesenden Methoden sowie den neuen Methoden »remove_prefix()« und »remove_suffix()« (Listing 1).

Listing 1

string_view.cpp

01 #include <iostream>
02 #include <string>
03 #include <experimental/string_view>
04
05 int main(){
06
07     std::string str = "   A lot of space";
08     std::experimental::string_view strView = str;
09     strView.remove_prefix(std::min(strView.find_first_not_of(" "), strView.size()));
10     std::cout << "str      :  " << str << std::endl
11               << "strView  : " << strView << std::endl;
12
13     std::cout << std::endl;
14
15     char arr[] = {'A',' ','l','o','t',' ','o','f',' ','s','p','a','c','e','\0', '\0', '\0'};
16     std::experimental::string_view strView2(arr, sizeof arr);
17     auto trimPos = strView2.find('\0');
18     if(trimPos != strView2.npos) strView2.remove_suffix(strView2.size() - trimPos);
19     std::cout << "arr     : " << arr << ", size=" << sizeof arr << std::endl
20               << "strView2: " << strView2 << ", size=" << strView2.size() << std::endl;
21
22 }

Das Programm birgt keine großen Überraschungen. In den Zeilen 8 und 16 erhalten die »std::string_view« -s Referenzen auf den C++-String beziehungsweise das Zeichenarray. Während »strView.find_first_not_of(" ")« in Zeile 9 alle führenden Zeichen entfernt, die kein Leerzeichen sind, löscht »strView2.find('\0')« in Zeile 18 alle abschließenden Spaces.

Um das Programm auszuführen, bietet sich der Online-Compiler [4] an. Mit Hilfe eines hochaktuellen GCC 6.1 mit dem Flag »-std=C++17« lässt sich die neue Funktionalität in Aktion bewundern (Abbildung 1). Noch muss der Programmierer in Listing 1 den Namensraum »experimental« verwenden. Das wird unnötig, wenn C++17 verabschiedet ist.

Abbildung 1: Das Programm aus Listing 1 in Aktion.

Parallele Algorithmen

Weiter geht es mit alten Bekannten: der Standard Template Library. Sie enthält gut 100 Algorithmen für das Suchen, Zählen, Manipulieren von Bereichen und deren Elementen. C++17 überlädt die meisten der Algorithmen, Entwickler können sie mit einer so genannte Execution Policy aufrufen. Die bestimmt, ob das Programm den Algorithmus sequenziell, parallel oder vektorisiert ausführt.

Vektorisierung benutzt die SIMD-Erweiterung (Single Instruction, Multiple Data, [5]) moderner CPUs, die eine Operation parallel auf mehreren Daten ausführen kann. Welche überladene Version eines Algorithmus zum Tragen kommt, steuert der Anwender über das Policy Tag (Listing 2). Das Dokument P00024R2 [6] erklärt das Ganze.

Listing 2

Parallele Algorithmen

01 using namespace std;
02 vector<int> v = ...
03
04 // standard sequential sort
05 sort(v.begin(), v.end());
06
07 // explicitly sequential sort
08 sort(sequential, v.begin(), v.end());
09
10 // permitting parallel execution
11 sort(par, v.begin(), v.end());
12
13 // permitting vectorization as well
14 sort(par_vec, v.begin(), v.end());

Schön ist an dem kleinen Beispiel in Zeile 5 zu sehen, dass die klassische Variante von »std::sort« mit C++17 immer noch zu Verfügung steht. Dagegen lässt sich mit C++17 jetzt explizit die sequenzielle (Zeile 8), die parallele (Zeile 11) oder auch die vektorisierende (Zeile 14) Variante von »std::sort« anfordern. Doch Vorsicht: Für die richtige Anwendung der Algorithmen ist der Anwender verantwortlich. Die Algorithmen schützen nicht per se vor Race-Conditions (kritischer Wettlauf) oder Deadlocks (Verklemmungen). Welche parallelen Algorithmen C++17 anbietet, kann das erwähnte Dokument P00024R2 [6] in Abbildung 2 ebenfalls erklären.

Abbildung 2: Liste der parallelen Algorithmen in C++17.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 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

    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

    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.

  • C++11

    Der Smart Pointer gilt als der klügste seiner Art in C++11. Sein Fachgebiet ist die elegante Garbage Collection, manchmal muss aber sein kleiner Bruder Weak Pointer mithelfen.

  • C++

    Implizite Typkonvertierungen sind eine der Ursachen für undefiniertes Verhalten in C- und C++-Programmen. In Kurzform bedeutet dies, dass solche Programme alles Mögliche tun dürfen und unvorhersehbar reagieren. C++-Routinier Rainer Grimm zeigt, wie C++-Entwickler diese Falle umgehen.

comments powered by Disqus

Stellenmarkt

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