Automatik und Typ-Erkennung
Das Ausführen des fertigen Programms aus Listing 5 führt zur Ausgabe »myAdd(1,2): 3«. Neben »auto«, das den Typ aus einem Initializer ableitet, enthält C++0x noch das Schlüsselwort »decltype«, das den Typ aus einem Ausdruck ermittelt. Es ist ein mächtiges Werkzeug in generischen Kontexten, in denen der Ergebnistyp aus einer Operation nur schwer zu ermitteln ist. Der Ausdruck »decltype(myVecInt[0]*myDoubleInt[0]) myDouble« deklariert in Listing 6 »myDouble« vom Typ »double«.
Weiter geht es mit Neuerungen zum generischen Programmieren: Variadic Templates können mit einer beliebigen Zahl von Template-Argumenten umgehen. Ein praktisches Beispiel: Listing 7 verwendet Variadic Templates. Die Template-Funktion »f()« nimmt beliebig viele Argumente an und gibt deren Anzahl zurück. »printCommaSeparatedList()« erwartet ein oder mehrere Argumente und gibt diese kommasepariert aus.
Abbildung 4 zeigt die Ausgabe des Programms. Das Entscheidende sind die drei Punkte, die entweder links in »template <typename... Args>« oder in »int f(Args... args){« rechts vom Parameter »Args« stehen. Links packt der Ellipsen-Operator »...« das so genannte Parameter Pack, rechts entpackt er es wieder. Eine Besonderheit ist der neue Operator »sizeof ...« (Zeile 7), der direkt mit Parameter Packs umgehen kann.
Abbildung 4: Variadic Templates können mit einer beliebigen Zahl von Argumenten umgehen – die Ausgabe von Listing 7.
|
Listing 7: Variadic |
|---|
01 #include <iostream>
02 #include <string>
03 #include <vector>
04
05 template <typename... Args>
06 int f(Args... args){
07 return (sizeof... args);
08 }
09
10 template<typename T>
11 void printCommaSeparatedList(T value)
12 {
13 std::cout<<value<<std::endl;
14 }
15
16 template<typename First,typename ... Rest>
17 void printCommaSeparatedList(First first,Rest ... rest)
18 {
19 std::cout<<first<<",";
20 printCommaSeparatedList(rest...);
21 }
22
23
24 int main() {
25 std::cout << "n";
26
27 auto intList= {1,2,3};
28 std::vector <int> intVec= {1,2,3,4,5};
29
30 std::cout << "f() has " << f() << " argumentsn";
31 std::cout << "f(42, 3.14) has " << f(42, 3.14) << " argumentsn";
32 std::cout << "f("one","two","three","four") has " << f("one","two","three","four" ) << " argumentsn";
33 std::cout << "f(intVec,intList) has " << f(intVec,intList) << " argumentsnn";
34
35 printCommaSeparatedList("Only primary template used.");
36 printCommaSeparatedList(42,"hello",2.3,'a');
37 std::cout << "n";
38 }
|
|
Listing 8: |
|---|
01 constexpr int square(int x) { return x * x; }
02 int values[square(7)];
|
Rekursion
Deutlich ungewohnter zeigt sich die Template-Funktion »printCommaSeparatedList()«. Sie besteht aus dem Template in Zeile 10, das nur ein Argument erwartet und dem gleichnamigen Template in Zeile 16, das mehr als ein Argument erwartet. Beim Aufruf mit einem einzigen Argument, beispielsweise mit
printCommaSeparatedList("Only primary U template used.");
kommt das Template mit einem Argument zum Einsatz und gibt den String aus. Dagegen stößt der Aufruf
printCommaSeparatedList(42,"hello",2.3,'a');
die Rekursion an, gibt das erste Argument mit der Anweisung »std::cout <<first<<",";« aus und ruft sich rekursiv mit der Anweisung »printCommaSeparatedList(rest...);« auf. Dieser Prozess kommt genau dann zum Erliegen, wenn »rest« nur noch ein Element enthält, denn jetzt wird das Template mit einem Argument verwendet.
Pattern Matching und rekursive Aufrufe sind elementare Bausteine der funktionalen Programmierung [8]. Ein interessanteres Beispiel für Variadic Templates ist die Funktion »printf()« [9]: Im Gegensatz zu ihrem C-Pendant ist sie typsicher.
Die Technik Template Metaprogramming [10] zeichnet sich dadurch aus, dass der Code zur Compilezeit ausgeführt wird und somit zur Laufzeit bereits als Konstante zur Verfügung steht.
Damit das funktioniert, müssen sich die Ausdrücke zur Compilezeit evaluieren lassen. Genau dies bewirkt das neue Schlüsselwort »constexpr« in Listing 8. Damit lassen sich einfache Funktionen, die einen Return-Wert besitzen, sowie auch Objekte auswerten. Das Array in Listing 7 beispielsweise lässt sich in C++0x über die Compilezeit-Konstante initialisieren. Die genaueren Forderungen an »constexpr« sind im Wikipedia-Eintrag unter [11] nachzulesen.
Das Schlüsselwort »static_assert« macht es möglich, konstante Ausdrücke ohne die Magie des Template Metaprogramming zur Compilezeit zu evaluieren. Dies ist besonders hilfreich, weil der Programmierer mit »static_assert« Voraussetzungen für die Templateparameter prüfen kann. Der Ausdruck
static_assert(sizeof(int) == 4, "This code U only works for sizeof(int) == 4");
stellt sicher, dass »int« die richtige Größe besitzt, und führt im Fehlerfall dazu, dass das Kompilieren abbricht und der String »"This code only works for sizeof(int) == 4")« ausgegeben wird.
Diesen Artikel als PDF kaufen
Express-Kauf als PDF
Umfang: 5 Heftseiten
Preis € 0,99
(inkl. 19% MwSt.)
Als digitales Abo
Weitere Produkte im Medialinx Shop »
Versandartikel
Onlineartikel
Alle Rezensionen aus dem Linux-Magazin
- Buecher/07 Bücher über 3-D-Programmierung sowie die Sprache Dart
- Buecher/06 Bücher über Map-Reduce und über die Sprache Erlang
- Buecher/05 Bücher über Scala und über Suchmaschinen-Optimierung
- Buecher/04 Bücher über Metasploit sowie über Erlang/OTP
- Buecher/03 Bücher über die LPI-Level-2-Zertifizierung
- Buecher/02 Bücher über Node.js und über nebenläufige Programmierung
- Buecher/01 Bücher über Linux-HA sowie über PHP-Webprogrammierung
- Buecher/12 Bücher über HTML-5-Apps sowie Computer Vision mit Python
- Buecher/11 Bücher über Statistik sowie über C++-Metaprogrammierung
- Buecher/10 Bücher zu PHP-Webbots sowie zur Emacs-Programmierung
Insecurity Bulletin
Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...





