Open Source im professionellen Einsatz
Linux-Magazin 05/2010
882

Programmieren höherer Ordnung

Der generische Adapter »std::bind« ermöglicht in Kombination mit der neuen Funktion »std::function« das Programmieren höherer Ordnung [11] in C++0x. Mit »std::bind«, das die C++-Funktionsadapter »std::bind1st« und »std::bind2nd« auf generische Stufe stellt, kann der Entwickler Argumente an beliebige Positionen einer Funktion, einer Methode oder eines Funktionsobjekts binden. Das resultierende Funktionsobjekt kann er direkt aufrufen oder in einem Funktionsobjekt (»std::function«) speichern. Darüber hinaus lassen sich für Argumente ohne Wert Platzhalter verwenden. Die Funktionsobjekte, die »std::function« bindet, sind First Class Functions [11].

Die Umwandlung einer Funktion mit mehreren Argumenten in mehrere Funktionen mit je einem Argument, in der funktionalen Programmierung unter dem Namen Currying [12] bekannt, ist nun auch in C++0x möglich.

Die Funktionalität von »std::bind« lässt sich oft durch Lambdafunktionen ausdrücken, jene von »std::function« durch die Type-Inference von »auto«. Beides steht bereits mit der C++0x-Kernsprachen-Erweiterung zur Verfügung [1]. Welche Variante der Entwickler wählt, bleibt im Grunde seinem Geschmack überlassen (Listing 11).

Listing 11: »bind«
und »function«

01 template <typename T>
02 T addMe(T a, T b){
03     return a+b;
04 };
05 
06 std::function<std::string(std::string)> addString =std::bind(addMe<std::string>,"first",_1);
07 std::cout << addString("second") << std::endl;
08 
09 auto addString2= std::bind(addMe<std::string>, "first",_1);
10 std::cout << addString2("second") << std::endl;
11 
12 std::vector<int> myVec{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
13 
14 std::copy_if( myVec.begin(), myVec.end(),
15               std::ostream_iterator<int>( std::cout, ", " ),
16               std::bind( std::logical_and<bool>(),
17                    std::bind( std::greater <int>(),_1,9 ),
18                    std::bind( std::less <int>(),_1,16 )));
19 
20 std::copy_if( myVec.begin(), myVec.end(),
21               std::ostream_iterator<int>( std::cout, ", " ),
22               [](int a){ return (a>9)&&(a<16);});

Zeile 6 erzeugt ein Funktionsobjekt, das »first« an das erste Argument bindet. Für das zweite Argument kommt der Platzhalter »_1« zum Einsatz. Der Funktionsadapter »std::bind« erzeugt aus dem generischen Template, das zwei Argumente gleichen Typs erwartet, ein Funktionsobjekt, das einen »std::string« erwartet und einen »std::string« zurückgibt. Das entspricht genau der Deklaration von »std::function<std::string(std::string)>«. Das automatische Ableiten des Funktionsobjekt-Typs durch »auto addString2« aus dem Funktionsadapter ist in diesem Falle jedoch deutlich einfacher. Beide Funktionsobjekte geben »firstsecond« auf der Kommandozeile aus.

Im Gegensatz hierzu ist »std::copy_if« wesentlich ungewohnter zu lesen. Beide Kopieralgorithmen in Listing 11 geben jene Elemente von »myVec« (Zeilen 14 und 20) kommasepariert aus (Zeile 15 und Zeile 21), die sowohl größer als 9 als auch kleiner als 16 sind (Zeilen 16 bis 18 und 22). Das Ergebnis der beiden Algorithmen ist »10, 11, 12, 13, 14, 15«.

Abbildung 4: Der Technical Report 1 und damit die C++0x-Bibliotheken fußen auf Boost.

Aus- und Fernblick

Dieser Artikel bleibt zwangsläufig unvollständig, denn die neue C++0x-Standardbibliothek ist sehr umfangreich. Drei praktische Werkzeuge seien aber unbedingt noch genannt. Das erste ist die Bibliothek zur Erzeugung von Zufallszahlen [13], die aus zwei Teilen besteht: einem Generator, der Sequenzen von Zufallszahlen erzeugt, und einer Verteilung, die die Zufallszahlen in einem vorgegebenem Bereich verteilt. Zweitens: Aktionen, die von anderen zeitlich abhängen, etwa »std::time_mutex«, benötigen Zeit-Tools. Auch diese hat C++0x im Repertoire [13]. In die dritte Kategorie der nützlichen Werkzeuge fallen jene Wrapper [14], die Referenzen umhüllen, sodass sich diese in Standardcontainern verwenden lassen.

Zwar ist der neue C++0x Standard noch nicht verabschiedet, doch es lässt sich bereits ein sehr detailliertes Bild von C++0x und seinen Bibliotheken zeichnen. Viele der neuen Features, insbesondere der neuen Bibliotheken, stehen mit einem aktuellen Compiler wie GCC 4.5 schon zur Verfügung. Da stellt sich die Frage, was auf C++0x noch folgen soll: Nach dem Technical Report 1 [15], der auf den Boost-Bibliotheken (Abbildung 4) aufbaut, folgt Technical Report 2 [16]. Er soll sich vor allem mit Unicode, XML/HTML, Netzwerkprogrammierung und der Usability der Standardbibliothek für C++-Novizen befassen. (mhu)

Infos

[1] Rainer Grimm, "Erfrischend neu": Linux-Magazin 04/10, S. 116

[2] Herb Sutter, "The free lunch is over": [http://www.gotw.ca/publications/concurrency-ddj.htm]

[3] Artikel zum Memory Modell für C++: [http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/]

[4] RAII: [http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization]

[5] Deadlock: [http://de.wikipedia.org/wiki/Deadlock]

[6] Anthony Williams, "Simpler Multithreading in C++0x": [http://www.devx.com/SpecialReports/Article/38883]

[7] »std::async«: [http://www2.research.att.com/~bs/C++0xFAQ.html#std-async]

[8] Boost-Regex-Bibliothek: [http://www.boost.org/doc/libs/1_42_0/libs/regex/doc/html/index.html]

[9] Type-Traits-Bibliothek:[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=276]

[10] Hashtabellen: [http://de.wikipedia.org/wiki/Hashtabelle]

[11] Rainer Grimm, "Funktionale Programmierung (1): Grundzüge": [http://www.linux-magazin.de/Online-Artikel/Funktionale-Programmierung-1-Grundzuege]

[12] Currying: [http://de.wikipedia.org/wiki/Currying]

[13] Entwurf des C++0x-Standards: [http://www2.research.att.com/~bs/SC22-N-4411.pdf]

[14] Danny Kalev, "Reference Wrapper": [http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=217]

[15] Technical Report 1 (TR1): [http://www.boost.org/doc/libs?view=filtered_std-tr1]

[16] Technical Report 2 (TR2):[http://en.wikipedia.org/wiki/Technical_Report_2#Technical_Report_2]

Der Autor

Rainer Grimm arbeitet seit 1999 als Software-Entwickler bei der Science + Computing AG in Tübingen. Insbesondere hält er Schulungen für das hauseigene Produkt SC Venus.

Linux-Magazin kaufen

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

Deutschland

Ähnliche Artikel

  • 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++11

    Die neuen Smart Pointer in C++11 machen den Zugriff auf Ressourcen transparent und räumen hinter sich auf. Dieser Artikel stellt als ersten Vertreter den Unique Pointer vor.

  • C++11

    Klein, aber oho: Platziert ein Entwickler drei Punkte ("…") geschickt an der richtigen Stelle im C++-Code, entpacken die so genannten Variadic Templates ihre Argumente an Ort und Stelle.

  • C++11

    2014 ist ein besonderes Jahr für C++. Drei Jahre nach C++11 erfährt der Sprachstandard mit C++14 den letzten Feinschliff. Neben generischen Lambda-Funktionen und der vereinfachten Ermittlung des Rückgabetyps kann C++14 vor allem mit einem Feature punkten: Reader-Writer-Locks.

  • 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.

comments powered by Disqus

Stellenmarkt

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