Über den praxisrelevanten Einsatz der Template-Metaprogrammierung

Template-Metaprogrammierung (TMP) scheint prädestiniert dafür, in einer Glasvitrine im Elfenbeinturm der C++-Sprachwissenschaftler zur Schau gestellt zu werden.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 17 Min.
Von
  • Marc Mutz
Inhaltsverzeichnis

Die Template-Metaprogrammierung (TMP) scheint prädestiniert dafür, in einer Glasvitrine im Elfenbeinturm der C++-Sprachwissenschaftler zur Schau gestellt zu werden. Und doch sieht man sich plötzlich wieder "#include <boost/mpl/..." tippen. heise Developer begibt sich auf die Suche nach einem praxisrelevanten Einsatz von TMP.

So wie man normalerweise neue Programmiersprachen mit einem "Hello, World"-Programm einführt, so geben die gängigen Erklärungen (etwa Wikipedia) in das Thema TMP (mittlerweile) klassische, aber nutzlose Beispiele wie die Berechnung der Fakultät einer Ganzzahl oder das Parsen von Binärzahlen zur Compilezeit (der Exkurs am Ende des Artikels stellt hier keine Ausnahme dar).

Mehr Infos

Wer sich schnell noch mal schlau machen will, für was Template Meta-Programming (TMP) und die Meta-Programming Library (MPL) stehen, kann das im "Exkurs: TMP kurz und bündig" im Anschluss an den Artikel tun.

Genauso wenig wie man eine Programmiersprache anhand eines "Hello, World" einschätzen kann, gehen solcherlei Veranschaulichungen am Kern von TMP vorbei: Bei TMP rechnet man nicht mit Zahlen, sondern mit Typen. Nach dieser Erkenntnis ist es gleichwohl schwierig, praxisrelevante Beispiele zu finden, die zudem noch funktionieren, wenn man sie aus ihrem eigentlichen Zusammenhang reißt. Die Konvertierung von Boost.Variant nach QVariant und umgekehrt eignet sich jedoch hervorragend dazu.

Mehr Infos

Wer von Boost.Variant oder QVariant noch nie etwas gehört hat, kann sich im "Exkurs: Boost.Variant versus QVariant" im Anschluss an den Artikel den nötigen Hintergrund anlesen.

Der Autor hatte vor ein paar Jahren das Vergnügen, an einem Projekt zu arbeiten, in dem sowohl Boost als auch Qt (damals noch in Version 3) Verwendung fanden. Heutzutage ist das Gang und Gäbe, damals war es noch unheimlich aufregend. Das zentrale Datenmodell verwendete Boost.Variant in der API, um eine Palette unterschiedlicher Datentypen zurückgeben zu können. Mit diesem Klassen-Template konnte der Autor damals folgende API implementieren, ohne für jeden Datentyp ein eigenes Getter/Setter-Paar definieren zu müssen:

typedef boost::variant<int,float,double,std::string/*,...*/> Variant;
class Attribute {
public:
    // ...
    Variant data() const;
    void setData( const Variant & v );
};

Es sei nun ein kleiner Sprung vorwärts auf der Zeitachse vorgenommen: Zwischenzeitlich hatte der Autor die Anwendung nach Qt 4 portiert und arbeitete mittlerweile an einem QAbstractItemModel zur Visualisierung des zentralen Datenmodells (das mit Boost.Variant in der API) in einem QTreeView geschrieben. Auch im QAbstractItemModel finden sich – wie im Attribute des Autors – Variant-basierte Funktionen data() und setData():

class QAbstractItemModel : public QObject {
public:
    // ...
    QVariant data( const QModelIndex & index, int role ) const;
    bool setData( const QModelIndex & index,
                            const QVariant & value, int role );
};

Aber jetzt mit QVariant anstelle von Boost.Variant. Nun ist die Bühne bereitet, der Auftrag klar: Der Autor musste Konvertierungsfunktionen von Boost.Variant nach QVariant (und umgekehrt) schreiben.