Metafunktionen
Template Metaprogramming erzeugt den gewünschten C++-Sourcecode zur Compilezeit. Funktionen und Daten, die zur Compilezeit zur Anwendung kommen, nennt man Metafunktionen und Metadaten. Metafunktionen sind Klassentemplates (Zeilen 4 und 9 in Listing 3), der C++-Funktion »myFunction(arg1,arg2)«
etwa entspricht die Metafunktion »My Function<Arg1,Arg2>«
.
Das Ergebnis der Metafunktion wird per Konvention, falls es ein Typ ist, durch »::type«
(Zeile 30), falls es eine integrale Konstante ist, durch »::value«
(Zeile 14 in Listing 2) zur Verfügung gestellt. Diese Konvention erleichtert das Programmieren mit Metafunktionen deutlich, da Metafunktionen mehrere Returnwerte zurückgeben können.
Typen und integrale Daten sind die Metadaten, auf denen Metafunktionen wirken. Metadaten werden aber nicht modifiziert, sondern auf Anfrage neu erzeugt. Zur Compilezeit gibt es keine Variablen, sondern nur symbolische Namen. Da C++ weder String- noch Fließkommakonstanten als Templateparameter erlaubt, lassen sich diese beim Template Metaprogramming nicht verwenden. Als Case-Struktur zur Compilezeit dient bei dieser Programmiertechnik Pattern Matching in Form partieller oder vollständiger Templatespezialisierung. Template Metaprogramming setzt Pattern Matching nach dem Best-fit-Prinzip ein, das die am genauesten passende Variante auswählt. Dies steht im Gegensatz zum vertrauteren Pattern Matching nach dem First-fit-Prinzip, das bei Ausnahmebehandlung in C++, Java oder Python gilt.
Die C++-Syntax verlangt, dass der Programmierer das primäre Template (Zeile 4 in Listing 3) als erstes zumindest deklariert, bevor er die Spezialisierungen (Zeile 9) definiert. Pattern Matching und Rekursion als Strukturelemente (Listing 2), die Abwesenheit von Variablen – die Anzeichen häufen sich, dass Template Metaprogramming eine funktionale Sprache ist. Grund genug, sich zu fragen: Lässt sich mit Template Metaprogramming im funktionalen Stil programmieren?
Map macht's möglich
Neben »filter«
und »reduce«
ist »map«
die klassische Funktion aus der funktionalen Programmierung. Sie nimmt eine Funktion und eine Liste an und gibt eine neue Liste zurück, indem sie die Funktion auf jedes Listenelement anwendet. Was liegt näher, als sie als Metafunktion umzusetzen? Die zwei elementaren Bausteine, um zur Compilezeit Listen zu implementieren, sind Variadic Templates [3] und der Container »std::tuple«
[2]. Beide finden sich im kommenden C++0x-Standard und können mit beliebig vielen Argumenten umgehen. Wie die Klassentemplates auf »std::tuple«
beziehungsweise wie Metafunktionen auf Metadaten wirken, zeigt Listing 4.
Listing 4
Die Map-Funktion zur Compilezeit
01 #include <iostream>
02 #include <tuple>
03
04 // Int2Type
05
06 template <int v>
07 struct Int2Type {
08 const static int value= v;
09 };
10
11 // a few class templates
12
13 struct ApplyId{
14 template<typename T>
15 struct apply{
16 typedef Int2Type<T::value> type;
17 };
18 };
19
20 struct MakeTen{
21 template<typename T>
22 struct apply{
23 typedef Int2Type<10> type;
24 };
25 };
26
27 struct DoubleMe{
28 template<typename T>
29 struct apply{
30 typedef Int2Type<2*(T::value)> type;
31 };
32 };
33
34 struct AbsMe{
35 template<typename T>
36 struct apply{
37 typedef Int2Type< (T::value > 0)? T::value : -(T::value) > type;
38 };
39 };
40
41 // helper function for output
42
43 template< typename head >
44 void showMe( std::tuple< head> ){
45 std::cout << head::value << "\n";
46 };
47
48 template< typename head, typename ... tail>
49 void showMe( std::tuple< head, tail ... > ){
50 std::cout << head::value << " ," ;
51 showMe( std::tuple< tail ...>() );
52 }
53
54 // map function
55
56 template<typename F, typename ... Elements> struct map;
57
58 template< typename F, typename ... Elements>
59 struct map<F,std::tuple<Elements ...> >{
60 typedef std::tuple<typename F::template apply<Elements>::type ... > type;
61 };
62
63 int main(){
64
65 std::cout << "original tupel: " << std::endl;
66 typedef std::tuple<Int2Type<-5>,Int2Type<-4>,Int2Type<-3>,Int2Type<-2>,Int2Type<-1>,Int2Type<0>,
67 Int2Type<1>,Int2Type<2>,Int2Type<3>,Int2Type<4>,Int2Type<5> >constNumbers;
68 showMe( constNumbers() );
69
70 std::cout << "\napply identity: " << std::endl;
71 typedef map<ApplyId, constNumbers >::type idConstNumbers;
72 showMe( idConstNumbers() );
73
74 std::cout << "\nset each value to 10" << std::e ndl;
75 typedef map<MakeTen, constNumbers >::type makeTenConstNumbers;
76 showMe( makeTenConstNumbers() );
77
78 std::cout << "\ndouble each value" << std::endl;
79 typedef map<DoubleMe, constNumbers >::type doubleMeConstNumbers;
80 showMe( doubleMeConstNumbers() );
81
82 std::cout << "\nabsolute value" << std::endl;
83 typedef map<AbsMe, constNumbers >::type absMeConstNumbers;
84 showMe( absMeConstNumbers() );
85
86 };
Vor der Theorie kommt die Praxis. Kompiliert und ausgeführt, ergibt der Quelltext die Ausgabe in Abbildung 4. Das Programm besteht aus der »map«
-Metafunktion (Zeile 56), die beliebig viele Argumente annimmt, sie in ein »std::tuple«
verpackt und die Metafunktionen »ApplyId«
, »MakeTen«
, »DoubleMe«
und »AbsMe«
auf ihre einzelnen Argumente (Zeile 60) anwendet. Das einfache Funktionstemplate »showMe«
gibt den Container zu Laufzeit aus.
Diesen Artikel als PDF kaufen
Express-Kauf als PDF
Umfang: 7 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...





