- C-Plusplus-Metaprogrammierung
-
C++-Metaprogrammierung bezeichnet die Technik der Metaprogrammierung innerhalb der Programmiersprache C++, also eine Technik, um in C++ Programmcode von Programmcode generieren zu lassen. Dabei kommen besonders Templates zum Einsatz, daher spricht man auch von Templatemetaprogrammierung. Es gibt aber auch Metaprogrammierung mittels C-Makros.
Inhaltsverzeichnis
Funktionsweise
Bei der Templatemetaprogrammierung macht man sich zu nutze, dass Templates während des Kompilierens ausgewertet werden. So kann man mit Hilfe von Templatespezialisierung Code schreiben, der zur Kompilationszeit ausgewertet wird und erst den eigentlichen Code generiert. Dies verlängert zwar die Dauer des Kompilierens, verkürzt aber die Laufzeit.
Die Templatemetaprogrammierung ist eine mächtige Programmiertechnik, die für C++ intensiv erforscht und ausentwickelt wurde. So gibt es zum Beispiel eine Implementierung eines Lisp-Derivats [1] oder einen mit Hilfe von C++-Templates realisierten Parsergenerator [2].
Krzysztof Czarnecki und Ulrich W. Eisenecker gelten als die Vordenker dieser Technik. Herausragende Arbeiten zur C++-Metaprogrammierung stammen insbesondere von Andrei Alexandrescu, die er besonders mit seinem Buch Modernes C++ Design – Generische Programmierung und Entwurfsmuster angewendet und die in dem Buch entwickelte Loki-Bibliothek bekannt machte.
Ein Nachteil der Metatemplateprogrammierung besteht darin, dass es in den bestehenden Entwicklungswerkzeugen keine Möglichkeiten gibt, die Metagenerierung schrittweise zu verfolgen. Aufgrund fehlender Sprachmittel ist es bislang auch schwierig, sinnvolle Fehlermeldungen für die Metaprogrammierung auszugeben, so dass man häufig mit einer enormen Menge an Fehlermeldungen konfrontiert wird, aus denen man nur schwer auf den eigentlichen Fehler rückschließen kann.
Die Template-Metaprogrammierung in C++ ist Turing-vollständig, was bedeutet, dass jeder Algorithmus durch Template-Metaprogrammierung umgesetzt werden kann.
In der Template-Metaprogrammierung gibt es keine veränderbaren Variablen, d.h. einmal mit einem bestimmten Wert initialisierte Elemente behalten ihren Wert für immer. Eine Konsequenz daraus ist, dass C++-Template-Metaprogramme generell – anders als C++-Laufzeitprogramme – eine Form der funktionalen Programmierung darstellen. Die Flusskontrolle erfolgt deshalb in der Template-Metaprogrammen mit Hilfe von Rekursion (so auch im Beispiel).
Beispiele
Potenzberechnung mit Hilfe von Metatemplates
#include <iostream> template<long B, unsigned long E> struct pow_helper { static long const value = B * pow_helper<B, E - 1>::value; }; template<long B> struct pow_helper<B, 0> { static long const value = 1; }; template<long B, long E> struct power { static double const value; }; template<long B, long E> double const power<B, E>::value= E < 0 ? 1.0 / pow_helper<B, E < 0 ? -E : 0>::value : pow_helper<B, E < 0 ? 0 : E>::value; int main() { std::cout << power<10, -3>::value << std::endl; }
Der Code funktioniert so, dass das Template power aufgerufen wird. Dieses wertet nun aus, ob der Exponent negativ ist und rechnet in dem Fall . Zum Berechnen der eigentlichen Potenz wird die Struktur pow_helper benutzt. Diese ruft sich selbst auf („Rekursion“), wobei der Exponent bei jedem Aufruf um 1 reduziert wird. pow_helper besitzt eine so genannte Spezialisierung für den Fall, dass der Exponent 0 ist und liefert in dem Fall das Ergebnis 1 zurück.
Also lässt sich der Code als
P(B, E) := B * P(B, E-1) P(B,-E) := 1 / P(B, |E|) P(B, 0) := 1
etwas leserlicher beschreiben.
Konsistenzprüfung mit Hilfe der Metaprogrammierung
Ein weiteres Beispiel:
template<bool> class StaticAssert; // Klassentemplate-Deklaration template<> class StaticAssert<true> {}; // Definition der Templatespezialisierung für true void f() { const bool test = false; StaticAssert<test> t; // Es existiert keine Klassen''definition'' für StaticAssert<false>. Dies // führt zu einer Fehlermeldung des Compilers. }
Dabei gibt ein Compiler eine Fehlermeldung aus. Dies lässt sich zu Konsistenzprüfungen des Programms ausnutzen (vgl. Assertion), kann jedoch nur zum Testen konstanter, zur Kompilationszeit bekannter Ausdrücke verwendet werden.
Vor- und Nachteile der Template-Metaprogrammierung
- Abwägung zwischen Übersetzungszeit und Ausführungszeit: Da der gesamte Template-Quelltext während der Übersetzung verarbeitet, ausgewertet und eingesetzt wird, dauert die Übersetzung insgesamt länger, während der ausführbare Code dadurch an Effizienz gewinnen kann.
- Generische Programmierung: Template-Metaprogrammierung erlaubt es dem Programmierer, sich auf die Architektur des Programms zu konzentrieren und dem Compiler die Erzeugung von jeglichen Implementierungen, die vom aufrufenden Quelltext benötigt werden, zu überlassen. Daher kann Template-Metaprogrammierung zu kürzerem Quelltext und erhöhter Wartbarkeit führen.
- Lesbarkeit: Verglichen mit konventioneller C++-Programmierung wirken Syntax und Schreibweisen der Template-Metaprogrammierung ungewohnt. Fortgeschrittene oder sogar die meiste nicht-triviale Template-Metaprogrammierung kann daher schwer zu verstehen sein. Dadurch können Metaprogramme von Programmierern, die in Template-Metaprogrammierung unerfahren sind, schwer zu pflegen sein. Letzteres hängt allerdings auch davon ab, wie die Template-Metaprogrammierung im speziellen Fall umgesetzt wurde.
- Portierbarkeit: Die Portierbarkeit von Quelltext, der von Template-Metaprogrammeriung starken Gebrauch macht, kann auf Grund von Unterschieden zwischen den verschiedenen Compilern eingeschränkt sein.
Siehe auch
Weblinks
- Loki-Lib
- Boost::MPL
- Andrei Alexandrescus Homepage
- Objektorientierte Programmierung für Dummies - Bonuskapitel Template-Metaprogrammierung
Literatur
- Krzysztof Czarnecki, Ulrich W. Eisenecker: Generative Programming - Methods, Tools, and Applications. Addison-Wesley, o.O. o.J.; ISBN 0-201-30977-7
- Andrei Alexandrescu: Modernes C++ Design - Generische Programmierung und Entwurfsmuster angewendet. mitp, o.O. o.J.; ISBN 3-8266-1347-3 - Standardwerk zur C++-Metaprogrammierung
- David Abrahams, Aleksey Gurtovoy: C++ Template Metaprogramming. Addison-Wesley, o.O. o.J.; ISBN 0-321-22725-5
- David Vandervoorde, Nicolai M. Josuttis: C++ Templates: The Complete Guide. Addison-Wesley Professional, o.O. o.J.; ISBN 0-2017-3484-2
- Michael McCool, Stefanus DuToit: Metaprogramming GPUs with Sh. A K Peters, o.O. o.J.; ISBN 1568812299
Wikimedia Foundation.